jOOQ MERGE support for PostgreSQL conditional insert - sql

I had understood that jOOQ would simulate SQL MERGE on systems (such as PostgreSQL) that don't support it.
I have a table with a serial (autoincrement) "id" column and a string "uri" column. I want to use numeric IDs instead of URIs in my database, so I have to make sure I have a URI in the ID lookup table. So following the example in the jOOQ manual, I thought this would work:
createDSLContext().mergeInto(tableByName("uris"))
.using(createDSLContext().selectOne())
.on(fieldByName("uri").equal("http://example.com/"))
.whenNotMatchedThenInsert(fieldByName("uri"))
.values("http://example.com/").execute();
This gives me a DataAccessException saying something like:
SQL [merge into "uris" using (select 1) on "uri" = ? when not matched then insert ("uri") values (?)]; ERROR: syntax error at or near "merge"
But then the log says jOOQ goes ahead and tries to execute the query with bind values. But the table is never updated. So I'm guessing the jOOQ doesn't simulate MERGE on PostgreSQL?
So I then try the H2 database syntax:
createDSLContext().mergeInto(tableByName("uris"), fieldByName("uri")).values(uri.toString()).execute();
I get:
The H2-specific MERGE syntax is not supported in dialect : POSTGRES
What!? But the jOOQ documentation says that the H2 syntax "can be fully simulated by jOOQ for all other databases that support the SQL standard." Surely PostgreSQL supports the SQL standard. Does it really mean "...the SQL standard version of MERGE?"
Is there any way to get PostgreSQL support for MERGE via jOOQ, or am I stuck doing the same workarounds I would do anyway?

To be sure if a given SQL feature is supported by jOOQ for your database, please consider the Javadoc's #Support annotation on the relevant DSL method. This is also documented in the manual. In this case, DSLContext.mergeInto(), where you can see that this statement is currently only supported for these SQLDialects:
#Support(value={CUBRID,DB2,HSQLDB,ORACLE,SQLSERVER,SYBASE})
MERGE is a very powerful statement that is not really easy to emulate if your database doesn't natively support it.
"can be fully simulated by jOOQ for all other databases that support the SQL standard." Surely PostgreSQL supports the SQL standard. Does it really mean "...the SQL standard version of MERGE?"
Yes of course, the SQL standard MERGE statement must be supported :-) We'll clarify this in the manual. I have registered issue #3183 for this.
Is there any way to get PostgreSQL support for MERGE via jOOQ, or am I stuck doing the same workarounds I would do anyway?
Right now, unfortunately, we don't have a solution for this in PostgreSQL. Feel free to discuss possible solutions on the jOOQ User Group.

Yes , it can support which database support the merge in SQL stand.
but postgresql unsupport this feature in SQL standard.
Please see
F312 MERGE statement
F313 Enhanced MERGE statement
F314 MERGE statement with DELETE branch
http://www.postgresql.org/docs/9.3/static/unsupported-features-sql-standard.html

Related

Understanding ODBC SQL Grammar - Need Catalog Examples

I've recently learned that ODBC has its own SQL grammar that eliminates SQL dialects, and thus makes all databases look "uniform". However, there is almost a complete absence of meaningful online documentation or discussion about this. Thus I don't have answers to questions like:
What is an example ODBC SQL statement(s) that catalogs all tables in a DB?
What is an example ODBC SQL statement that catalogs all columns in a table, or catalogs the primary key columns in a table?
To expand on the prior two questions, to achieve the same query results, what is an example of native (e.g. T-SQL) versus ODBC SQL?
How do I determine if the SQL I'm authoring is ODBC compliant? Note: I'm usually using SSMS.
Here is the quote that originally introduced me to the existence of an ODBC-specific SQL grammar:
In addition to a standard call-level interface, ODBC defines a standard SQL grammar. This grammar is based on the Open Group SQL CAE specification. MS ODBC Documentation
Elsewhere I found this quote:
Therefore, there are really two choices of grammar to use: the SQL-92 grammar (and the ODBC escape sequences) and a DBMS-specific grammar. Of the two, only the SQL-92 grammar is interoperable, so all interoperable applications should use it. MS docs 'choosing a SQL dialect'
I'd like to answer my own questions, and so I googled "SQL-92 query table catalog". The best I've found is from this link, which in turn offers an ODBC "Using Catalog Functions" link - which is broken. I creatively found a way to locate the "Using Catalog Functions" link myself, and found that it too is vague and provides no examples.
I'd really like to see actual examples, demonstrating true ODBC-compliant SQL catalog queries, and I've still not found anything.
Update
I just spotted my first-ever example code for fetching a catalog with ODBC. This has become very "Alice in Wonder Land" to discover the catalog functions, apparently, are not part of an alleged ODBC SQL grammar. Rather, apparently(?), they are part of (required) SDK signatures. Here is a C++ snippet from that link which demonstrates the SQLTables function.
// all catalogs query
printf( "A list of names of all catalogs\n" );
retCode = SQLTables( hstmt, (SQLCHAR*)SQL_ALL_CATALOGS, SQL_NTS, (SQLCHAR*)"", SQL_NTS, (SQLCHAR*)"", SQL_NTS, (SQLCHAR*)"", SQL_NTS );
for ( retCode = SQLFetch(hstmt) ; MySQLSuccess(retCode) ; retCode = SQLFetch(hstmt) )
printCatalog( catalogResult );
At this point, I don't know if the above example represents the bulk of my answer - or if it is just a nuanced part of the answer.

Is SELECT INTO T-SQL?

I'm working in a project where I have been explicitly required to not use T-SQL syntax. The application we are using supports T-SQL but we are not allowed to use it to avoid potential migration issues.
My question is: is the SELECT ... INTO statement T-SQL or SQL? If it is T-SQL, is there a specific SQL query to copy an existing table into a new one? (I have tried with CREATE TABLE AS .. FROM but it doesn't work).
Sounds like a very basic question but I haven't been able to find the answer anywhere. Thus, in addition to the question above, it would be very helpful to know if there is a guide/dictionary/website that collects only the standard SQL syntax.
Thanks!
I think they recommend you to use ANSI SQL, instead of T-SQL (SQL Server) or PL-SQL (ORACLE). Considering it as common requirement, every database vendor provide their own way of implementing this requirement. When you use ANSI SQL, you will not have migration issues, when you move from one database vendor to another database vendor.
SQL SERVER
SELECT * INTO new_table
FROM existing_table
ORACLE & ANSI-SQL
CREATE TABLE new_table
AS SELECT * FROM existing_table
is SELECT INTO TSQL or SQL?
Neither. The MySQL documentation claims that SELECT INTO is a Sybase extension to standard sql. As such I don't think you can accurately say it's either of these, but you can say that it's neither. It is indeed used in T-SQL, as well as some other database vendor products, to create a table from a query. The SQL standard says that queries with that goal should be formed as CREATE TABLE blah AS SELECT .... Oracle/MySQL, for example, use the standard form though you can see them use SELECT INTO in a different context, to assign data to variables in stored procedures
If you want to avoid use of this non standard syntax when creating and populating a table then you'll have to:
CREATE TABLE blah (column spec to match query output)
INSERT blah (select query here)
But then you run into nuances like "sqlserver calls it datetime/datetime2 but oracle calls it date/timestamp"
And ultimately you'll probably get into a situation where you just can't use one form of sql to do all you want..
I'd imagine most libraries that do data access on multiple underlying databases have mechanisms to use vendor specific terminology where required
From the answers, it appears you might need to specify which SELECT INTO you're talking about. The other answers seem to suggest there exists some kind of SELECT ... INTO <table-name> when there is also a kind of SELECT ... INTO <local-variable-name list>. The latter is used in embedded SQL for making SQL interact with variables of the host language program. I'm not certain but that variant may also be used in the part of the SQL language that deals with procedures written in SQL (the SQL/PSM part of the standard).
A "reference" that covers "only the standard SQL syntax" is, in principle, the ISO standard document itself, only available by purchase from ISO (and yes, it's ISO not ANSI - ANSI does nothing more than rubberstamping the ISO document after removing all the names of non-US contributors). And not the easiest kind of literature. There are "draft" versions floating around on the internet that might deviate from the published final standards. E.g. http://www.wiscorp.com/sql200n.zip. Note that this is a SQL:2008 draft. Current standard version is SQL:2011. And it's several thousands of pages, so I guess that covers your question "Is all the syntax covered in w3schools standard SQL". (Hint : no)

BigQuery DATE_DIFF Error: Encountered " <STRING_LITERAL>

I'm trying the following query from the BigQuery Standard SQL documentation:
SELECT DATE_DIFF(DATE '2010-07-07', DATE '2008-12-25', DAY) as days_diff;
https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators#date_diff
However, I'm receiving the following error from the UI:
Error: Encountered " "\'2010-07-07\' "" at line 1, column 23. Was expecting: ")" ... [Try using standard SQL (https://cloud.google.com/bigquery/docs/reference/standard-sql/enabling-standard-sql)]
This is a simple copy and paste from the doc into the web UI Query Editor.
Any idea on how to resolve this?
Below are examples for respectively BigQuery Legacy SQL and Standard SQL
Make sure you try code as it is in answer below - not just second lines but 2(both) lines including first line that looks like comment - but in reality important part of query as it controls which SQL dialect will be in effect!
#legacySQL
SELECT DATEDIFF(DATE('2010-07-07'), DATE('2008-12-25')) AS days_diff
and
#standardSQL
SELECT DATE_DIFF(DATE '2010-07-07', DATE '2008-12-25', DAY) AS days_diff
both returns result as below
Row days_diff
1 559
Ideally, you should consider migrating to Standard SQL
Although the answer has already been provided in the comments to your questions and by Mikhail in the other answer, let me share with you a complete answer that hopefully addresses all your doubts:
ERROR MESSAGE
As explained in the error message you are getting, [Try using standard SQL (...)]. You are trying to run this sample using Legacy SQL (which instead would use the DATEDIFF function). You are actually right, you are running the exact same query provided in the documentation, but the issue here is that the documentation you are using is for Standard SQL (the preferred query language in BigQuery), but you are instead using Legacy SQL (the default language in the old UI, the one you are using).
CHANGE THE QUERY LANGUAGE IN USE
First of all, I would like to remark the importance of using Standard SQL instead of Legacy SQL, as the former adds new functionalities and is the current recommended language to use with BigQuery. You can see the whole list of comparisons in the documentation, but if you are starting with BigQuery, I would just go straight away with Standard SQL.
Now, that being clarified, in order to use Standard SQL instead of Legacy SQL, you can have a look at the documentation here, but let me summarize the available options for you:
In the BigQuery UI, you can toggle the Use legacy SQL option inside
the Show options menu. If this option is marked, you will be using
Legacy SQL; and if it is not, you will be using Standard SQL.
You can use a prefix in your query, like #standardSQL or #legacySQL, which would ignore the default configuration and use the language you specify with this option. As an example on how to use it, please have a look at the other answer by Mikhail, who shared with you a couple of examples using prefixes to identify the language in use. You should copy the complete query (including the prefix) in the UI, and you will see that it works successfully.
Finally, as suggested by Elliott, you can use the new UI, which has just recently released in Beta access. You can access it through this link https://console.cloud.google.com/bigquery instead of the old link https://bigquery.cloud.google.com that you were using until now. You can find more information about the new BigQuery Web UI in this other linked page too.

PostgreSQL why/when should I use ECPG

I've decided to use postgreSQL as database for a game project(C++).
At the moment I'm using Oracle and it's Pro*C precompiler at work and heard that postgreSQL also has something similar called ECPG.
It's also possible to access data from the the postgres database directly by using the SQL in a string.
So the difference between "normal" and using ECPG, is that you can write your SQL statements like code?, or are there any other differences I should be aware of?.
(PS: i know I'm using it at work, but I haven't noticed any other differences)
Looking forward to hearing from you guys.
Yes, ECPG is covered in the documentation.
So the difference between "normal" and using ECPG, is that you can
write your SQL statements like code?
Well, SQL statements are code. A SQL statement just looks like a SQL statement. This is what a CREATE TABLE statement might look like in ECPG.
EXEC SQL CREATE TABLE foo (number integer, ascii char(16));
ECPG allows variable substitution. (Maybe that's what you meant by "write your SQL statements like code".)
EXEC SQL INSERT INTO sometable VALUES (:v1, 'foo', :v2);
All this stuff is in the documentation.

INSERT vs INSERT INTO

I have been working with T-SQL in MS SQL for some time now and somehow whenever I have to insert data into a table I tend to use syntax:
INSERT INTO myTable <something here>
I understand that keyword INTO is optional here and I do not have to use it but somehow it grew into habit in my case.
My question is:
Are there any implications of using INSERT syntax versus INSERT INTO?
Which one complies fully with the standard?
Are they both valid in other implementations of SQL standard?
INSERT INTO is the standard. Even though INTO is optional in most implementations, it's required in a few, so it's a good idea to include it if you want your code to be portable.
You can find links to several versions of the SQL standard here. I found an HTML version of an older standard here.
They are the same thing, INTO is completely optional in T-SQL (other SQL dialects may differ).
Contrary to the other answers, I think it impairs readability to use INTO.
I think it is a conceptional thing: In my perception, I am not inserting a row into a table named "Customer", but I am inserting a Customer. (This is connected to the fact that I use to name my tables in singular, not plural).
If you follow the first concept, INSERT INTO Customer would most likely "feel right" for you.
If you follow the second concept, it would most likely be INSERT Customer for you.
It may be optional in mySQL, but it is mandatory in some other DBMSs, for example Oracle. So SQL will be more potentially portable with the INTO keyword, for what it's worth.
In SQL Server 2005, you could have something in between INSERT and INTO like this:
INSERT top(5) INTO tTable1 SELECT * FROM tTable2;
Though it works without the INTO, I prefer using INTO for readability.
One lesson I leaned about this issue is that you should always keep it consistent! If you use INSERT INTO, don't use INSERT as well. If you don't do it, some programmers may ask the same question again.
Here is my another related example case: I had a chance to update a very very long stored procedure in MS SQL 2005. The problem is that too many data were inserted to a result table. I had to find out where the data came from. I tried to find out where new records were added. At the beginning section of SP, I saw several INSERT INTOs. Then I tried to find "INSERT INTO" and updated them, but I missed one place where only "INSERT" was used. That one actually inserted 4k+ rows of empty data in some columns! Of course, I should just search for INSERT. However, that happened to me. I blame the previous programmer IDIOT:):)
They both do the same thing. INTO is optional (in SQL Server's T-SQL) but aids readability.
I started wtiting SQL on ORACLE, so when I see code without INTO it just looks 'broken' and confusing.
Yes, it is just my opinion, and I'm not saying you should always use INTO. But it you don't you should be aware that many other people will probably think the same thing, especially if they haven't started scripting with newer implementations.
With SQL I think it's also very important to realise that you ARE adding a ROW to a TABLE, and not working with objects. I think it would be unhelpful to a new developer to think of SQL table rows/entries as objects. Again, just me opinion.
INSERT INTO is SQL standard while INSERT without INTO is not SQL standard.
I experimented them on SQL Server, MySQL, PostgreSQL and SQLite as shown below.
Database
INSERT INTO
INSERT
SQL Server
Possible
Possible
MySQL
Possible
Possible
PostgreSQL
Possible
Impossible
SQLite
Possible
Impossible
In addition, I also experimented DELETE FROM and DELETE without FROM on SQL Server, MySQL, PostgreSQL and SQLite as shown below:
Database
DELETE FROM
DELETE
SQL Server
Possible
Possible
MySQL
Possible
Impossible
PostgreSQL
Possible
Impossible
SQLite
Possible
Impossible
I prefer using it. It maintains the same syntax delineation feel and readability as other parts of the SQL language, like group BY, order BY.
If available use the standard function. Not that you ever need portability for your particular database, but chances are you need portability for your SQL knowledge.
A particular nasty T-SQL example is the use of isnull, use coalesce!