UPDATE syntax that works in major databases - mysql

I want to update a table (target) based on the values present in another table (source). But I am looking for a syntax that will work in 4 major databases - Oracle, MS SQL Server, PostgreSQL, MySQL.
So far, I am not able to find such a uniform syntax. Have I missed such syntax or there is really no such syntax?
Oracle
UPDATE target t
SET (t.col1, t.col2) = (SELECT s.col1, s.col2
FROM source s
WHERE s.key = t.key)
MS SQL Server / PostgreSQL
UPDATE target t
SET t.col1 = s.col1, t.col2 = s.col2
FROM source s
WHERE t.key=s.key
MySQL
UPDATE target, source
SET t.col1=s.col1, t.col2=s.col2
WHERE s.key=t.key

It is inefficient, but the ANSI SQL Standard way to do this is:
UPDATE target
SET col1 = (SELECT s.col1
FROM source s
WHERE s.key = target.key),
col2 = (SELECT s.col2
FROM source s
WHERE s.key = target.key);
This does not mean to say it will work in every RDBMS (e.g. I don't think it would work in Access), but it does work in the 4 you have listed.
I would personally value performance over portability every day of the week so I would not use this syntax. I would be inclined to use a use a stored-procedure, with a common name, but differing syntax for each RDBMS.
UPDATE
Actually, the method you have shown for Oracle using row value constructors is also allowed by the ANSI SQL Standard:
UPDATE target
SET (t.col1, t.col2) = (SELECT s.col1, s.col2
FROM source s
WHERE s.key = t.key);
Unfortunately, as mentioned above, just because it is in the ANSI Standards it does not mean that it works across platforms.

ANSI update syntax (it should work in DBMS that you listed):
update t1
set col1 = (
select col1
from t2
where t1.key = t2.key
),
set col2 = (
select col2
from t2
where t1.key = t2.key
)

Related

MySQL request for Node tree

I have a node tree in a MySQL Base and I want to get result like this
Node_1
Node_1_1
Node_1_1_1
Node_1_1_2
Node_1_2
Node_1_2_1
Node_2
Now I have a query that gives me only one deep child and all rests at the end of a list. ( Node_1_1_2 would be the last in this example )
Here is my code:
SELECT name,
if ( parentId = -1, "Root",
if ( exists( SELECT id FROM citizensTree AS t2 WHERE t1.id = t2.parentId), "Inner", "Leaf")
)
AS type FROM citizensTree as t1
I love this SQL solution:
SELECT t.id, t.name FROM tree t CONNECT BY prioir id = parentId START WITH parentId = -1
But it doesnt work in MySQL
The CONNECT BY is non-standard SQL syntax. It's supported by Oracle and Informix as far as I know, but definitely not MySQL.
MySQL 8.0 supports recursive queries using standard ANSI/ISO SQL syntax. See https://dev.mysql.com/doc/refman/8.0/en/with.html#common-table-expressions-recursive-examples
Earlier versions of MySQL do not support this syntax. You can simulate recursive queries using a variety of workarounds. See my answer to What is the most efficient/elegant way to parse a flat table into a tree?

Need help to convert below query from My SQL to MS SQL Group_Concat function

I need help to convert below query to MS SQL from my sql
SELECT
md.ID AS `ID`,
t1.Name AS `Name`,
group_concat(IF(t2.Column3 = 'Value1', t1.Value, NULL)) AS `Value1`,
group_concat(IF(t2.Column3 = 'Value2', t1.Value, NULL)) AS `Value2`,
group_concat(IF(t2.Column3 = 'Value3', t1.Value, NULL)) AS `Value3`
FROM Table1 t1
LEFT JOIN Table2 AS t2 ON t1.Column1 = t2.Column1
GROUP BY t1.Id ;
You can use STRING_AGG(expression, ',') in place of GROUP_CONCAT(expression), as of SQL Server 2017. For older versions, there seem to be several ways to do it (including installing a GROUP_CONCAT function), none of which I know enough of SQL Server to understand; see Simulating group_concat MySQL function in Microsoft SQL Server 2005? and links in that question.
And you can use CASE WHEN ... THEN ... ELSE ... END (or also just CASE WHEN ... THEN ... END if the else result is NULL) in place of IF(..., ..., ...). CASE is also valid in mysql.
But you will need to group by t1.Name or select something like MAX(t1.Name) instead, since you can't use non-aggregate columns that aren't grouped by (just as you can't in modern versions of mysql using modern default settings).
fiddle

Coldfusion ORM update with Join

I am looking for help on a HQL-statement, where I would like to do an update with a JOIN. I tried following statement, which runs fine in MySQL-Workbench:
UPDATE table1 t1
SET t1.status='Running'
JOIN t1.table2 t2
WHERE t1.status='Open' AND t2.destination ='mydestination' "
but it gives the error:
expecting "set", found 'JOIN' near line 1, column 16
It seems to me that as this is a bulk update operation then you should be using SQL for this not HQL. ORM is not really designed for this type of update. You can always run the SQL statement and then if you need to, load the object graph (your ORM entities) after.
As for the SQL you'll need to run it using cfquery (or the cfscript equivalent), from your HQL example it'd look something like this as SQL (assuming MySQL as you mention MySQL Workbench)
<cfquery>
UPDATE table1 t1
INNER JOIN table2 t2 ON t1.col = t2.col
SET status='Running'
WHERE status='Open'
AND t2.destination='mydestination'
</cfquery>
If you want to do it with HQL then you usually need to use a subquery. Something like this:
update table1 t1
set t1.status = 'Running'
where t1.state = 'Open'
and t1 in (
select t2.table1
from table2 t2
where t2.destination='mydestination'
)

operation must use an updateable query - access

I want to update a table by using the join in access - 2007
UPDATE TABLE1 A INNER JOIN (SELECT ACCODE, SUM(AMOUNT) AS SUM_AMOUNT
FROM TABLE2 GROUP BY ACCODE) B ON A.ACCODE = B.ACCODE
SET A.TRIAL = A.TRIAL + SUM_AMOUNT
it gives me error that
operation must use an updateable query
i have try with below query and no error is here
UPDATE TABLE1 A INNER JOIN TABLE2 B ON A.ACCODE = B.ACCODE
SET A.TRIAL = A.TRIAL + SUM_AMOUNT
please help me to find what is wrong with first query
I think the reason Access treats your query as non-updateable is due to the subquery GROUP BY. You should be able to create an updateable query by using DSum.
UPDATE TABLE1 AS a
SET a.TRIAL = a.TRIAL
+ DSum("AMOUNT", "TABLE2", "ACCODE=" & a.ACCODE)
If ACCODE is text instead of numeric data type, add quotes around the value in the DSum expression.
UPDATE TABLE1 AS a
SET a.TRIAL = a.TRIAL
+ DSum("AMOUNT", "TABLE2", "ACCODE='" & a.ACCODE & "'")
I just had this issue and it was due to permissions on the table. I made a copy of the linked table to test my update query on, and kept getting this error message. I was pretty sure my query would be ok (it was a simple update) so I ran it on the actual table and I didn't get the error. Just wanted to add this for anyone else that comes across this in the future!
this error also comes when you are accessing database which is on different PC. so give write permission from security tab of folder and also give write access on sharing permission option.
In my case this is worked
Yes Mandeep, that is the way ms-access works.
UPDATE Table1 As T1 INNER JOIN Table2 AS T2 ON T1.F1 = T2.F1
SET T1.F2 = T2.F2
This query raises 'operation must use an updateable query' erro when T2 is a query, even when you are not updating T2.

How does mysql delete syntax differ from select?

This:
SELECT *
FROM tbl_playlists, tbl_playlistsongs
WHERE tbl_playlists.playlist_id = tbl_playlistsongs.playlist_id
AND tbl_playlists.playlist_id = 1
...works no problem. But:
DELETE from tbl_playlists, tbl_playlistsongs
WHERE tbl_playlists.playlist_id = tbl_playlistsongs.playlist_id
AND tbl_playlists.playlist_id = 1
...says I have a syntax error. They're identical other than the SELECT * vs DELETE. It still makes perfect logical sense to me.. but I must be missing something!
Traditional SQL doesn't support multi-table deletions, but MySQL does. That means you're using MySQL specific syntax:
DELETE pl, pls
FROM TBL_PLAYLISTS pl
JOIN TBL_PLAYLISTSONGS pls ON pls.playlist_id = pl.playlist_id
WHERE pl.playlist_id = 1
Reference:
DELETE (MySQL documentation)