Complex UPDATE query in SQL Server 2008, rewrite from Oracle 10g - sql-server-2008

I need to re-write the following Oracle 10g query to work in SQL Server 2008
It's an update query, where some field are retrieved from a SELECT and some are given (from code).
UPDATE "BMAN_SQL"."CELLS_GLIST"
SET ("GLIST_ID", "GLIST_VALUE_ID") = (
SELECT "GLIST_ID", "GLIST_VAL_ID"
FROM "BMAN_SQL"."GLISTS_VAL_UOR"
WHERE ("UOR_ID"=3)
AND ("GLIST_CODE"='X')
),
"SESSION_ID" = 1553245736,
"USER_ID" = 13
WHERE EXISTS ( SELECT * FROM ... )
Note that I need to use the UPDATE SET ... WHERE EXIST ... structure for compatibility with Oracle (query are automatically built by a QueryBuilder class for each specific DBMS).
I also cannot write:
UPDATE "BMAN_SQL"."CELLS_GLIST"
SET ("GLIST_ID", "GLIST_VALUE_ID", "SESSION_ID", "USER_ID") = (
SELECT "GLIST_ID", "GLIST_VAL_ID", 1553245736, 13
FROM "BMAN_SQL"."GLISTS_VAL_UOR"
WHERE ("UOR_ID"=3)
AND ("GLIST_CODE"='X')
)
WHERE EXISTS ( SELECT * FROM ... )
because (as per this old thread Oracle "Cannot update to NULL") it returns an error if the SELECT does not fetch any record.
Thanks in advance!

You need to join update query in this case. Please see syntax below. <Your condition here> Replace this section with your join condition here.
UPDATE m
SET
GLIST_ID = r.GLIST_ID
,GLIST_VALUE_ID = r.GLIST_VAL_ID
, SESSION_ID= 1553245736
, USER_ID = 13
from BMAN_SQL.CELLS_GLIST m
inner join BMAN_SQL.GLISTS_VAL_UOR r on <Your condition here>
WHERE
r.UOR_ID=3 AND (r.GLIST_CODE='X') AND
EXISTS ( SELECT * FROM ... )
EDIT
UPDATE BMAN_SQL.CELLS_GLIST
SET
GLIST_ID = (SELECT TOP 1 GLIST_ID FROM BMAN_SQL.GLISTS_VAL_UOR WHERE (UOR_ID=3) AND (GLIST_CODE='X'))
,GLIST_VALUE_ID = (SELECT TOP 1 GLIST_VAL_ID FROM BMAN_SQL.GLISTS_VAL_UOR WHERE (UOR_ID=3) AND (GLIST_CODE='X'))
,SESSION_ID = 1553245736
,USER_ID = 13
WHERE EXISTS ( SELECT * FROM ... )

Related

Query blocking entirely MySQL server

I try to a run a specific query. However, when I execute it, the MySQL server doesn't respond anymore.
There is approximately 30000 rows in the table base_contrats_actifs but I don't know if this is a problem.
Here is the query :
UPDATE
base_contrats_actifs a
SET
a.code_indice = (
SELECT
MAX(g.code_indice)
FROM
base_gid g
WHERE
a.num_version = g.num_version_contrat
),
a.flag_bailleur_locataire = (
SELECT
MAX(g.flag_bailleur_locataire)
FROM
base_gid g
WHERE
a.num_version = g.num_version_contrat
),
a.compte_client = (
SELECT
MAX(g.compte_client)
FROM
base_gid g
WHERE
a.num_version = g.num_version_contrat
)
Can you see if there is an error ? If not, is there any way to debug the query ?
I don't know exactly why your update is non performant, but given the number of correlated subqueries you have, I'm not surprised. Try rewriting it as an update join:
UPDATE base_contrats_actifs a
INNER JOIN
(
SELECT
num_version_contrat,
MAX(code_indice) AS max_code_indice,
MAX(flag_bailleur_locataire) AS max_flag_bailleur_locataire,
MAX(compte_client) AS max_compte_client
FROM base_gid
GROUP BY num_version_contrat
) g
ON a.num_version = g.num_version_contrat
SET
a.code_indice = g.max_code_indice,
a.flag_bailleur_locataire = g.max_flag_bailleur_locataire,
a.compte_client = g.max_compte_client;

SQL run command if row exists

I'm new to MySQL and I'm trying to make the following pseudocode work:
SELECT IF(
EXISTS(SELECT * FROM users WHERE `email`="admin" AND `token`="blablabla"),
(UPDATE * FROM sometable WHERE `var`="notimportant"),
"NOT_AUTHORIZED");
What I'm trying to achieve is running code based on the presence of a row, and if it doesn't exists return a message, or something usable. If it does exists, run another SQL command instead, and return those results.
Is this possible?
Your intent is a bit hard to follow from the invalid syntax. But the gist of your question is that you can use a where clause:
UPDATE sometable
SET . . .
WHERE var = 'notimportant' AND
EXISTS (SELECT 1 FROM users WHERE email = 'admin' AND token = 'blablabla');
You can also represent this as a JOIN. Assuming the subquery returns at most one row:
UPDATE sometable t CROSS JOIN
(SELECT 1
FROM users
WHERE email = 'admin' AND token = 'blablabla'
LIMIT 1
) x
SET . . .
WHERE var = 'notimportant' ;

How to run concurring SQL query?

I am trying to run this sql query.
SELECT * FROM AverageFeedInfo WHERE No = (
SELECT No FROM UserResponse2 where Not Complain = '' )
When I run SELECT No FROM UserResponse2 where Not Complain = '' individually I have result 2 and 6, but if I run this
SELECT * FROM AverageFeedInfo WHERE No = (
SELECT No FROM UserResponse2 where Not Complain = '' )
I have only the result for 2 not for 6. Is it possible to get the answer for both 2 and 6. To be more clear is it possible to run the sql query like
SELECT * FROM AverageFeedInfo WHERE No = 2 or No = 6
Generally, when checking set membership in a SQL-based context use of an IN operator is more appropriate than =.

Update table with subquery works on mysql but error on oracle

I have table named TABLE_A looks like this :
ID DATA VALUE LM
---------------------------------
1 7 9 NULL
2 10 5 NULL
3 4 7 NULL
This is not actually my table, i use this to shorten my question.
Now I want to update table_a with subquery.
This is my query :
UPDATE TABLE_A,
(SELECT VALUE AS VAL FROM TABLE_A WHERE ID = 2) AS TEMP
SET TABLE_A.LM = TABLE_A.VALUE + TEMP.VAL
WHERE TABLE_A.ID = 1
This query works on Mysql but in oracle I got error :
[Err] ORA-00971: missing SET keyword
EDIT :
This is my table [SDM_ABSENSI] :
PERIODE TGL_IN TGL_OUT IN OUT LM TL
------------------------------------------------------------------
20141011 11/01/2014 11/01/2014 08:00 17:00 NULL NULL
20141012 12/01/2014 13/01/2014 22:00 07:30 NULL NULL
20141013 13/01/2014 13/01/2014 08:00 17:00 NULL NULL
My query :
UPDATE SDM_ABSENSI A
(
SELECT PERIODE, TGL_IN, TGL_OUT, IN, OUT,
TO_DATE(TO_CHAR(TGL_IN,'YYYY-MM-DD')||' '||IN,'YYYY-MM-DD hh24:mi') AS MASUK,
TO_DATE(TO_CHAR(TGL_OUT,'YYYY-MM-DD')||' '||OUT,'YYYY-MM-DD hh24:mi') AS KELUAR
FROM SDM_ABSENSI
WHERE SUBSTR(PERIODE,0,6) = '201410'
)ABSEN
SET A.LM = (24*60) * (ABSEN.KELUAR - ABSEN.MASUK),
A.TL = CASE WHEN (24*60) * (ABSEN.KELUAR - ABSEN.MASUK) < 0
THEN 0 ELSE (24*60) * (ABSEN.KELUAR - ABSEN.MASUK)
END
WHERE SUBSTR(A.PERIODE,0,6) = '201410'
AND A.PERIODE = ABSEN.PERIODE
And i got error :
[Err] ORA-00971: missing SET keyword
Please help,
Thanks in advance
Oracle does not support Update from Join Syntax. Instead you can use Merge. Try this.
MERGE
INTO SDM_ABSENSI
USING (
SELECT PERIODE, TGL_IN, TGL_OUT, IN, OUT,
TO_DATE(To_char(TGL_IN,'YYYY-MM-DD')||' '||IN,'YYYY-MM-DD hh24:mi') AS MASUK,
TO_DATE(TO_CHAR(TGL_OUT,'YYYY-MM-DD')||' '||OUT,'YYYY-MM-DD hh24:mi') AS KELUAR
FROM SDM_ABSENSI
WHERE SUBSTR(PERIODE,0,6) = '201410'
) ABSEN
ON SDM_ABSENSI.PERIODE = ABSEN.PERIODE
WHEN MATCHED THEN
UPDATE
SET SDM_ABSENSI.LM = ( 24 * 60 ) * ( ABSEN.KELUAR - ABSEN.MASUK ),
SDM_ABSENSI.TL = CASE
WHEN ( 24 * 60 ) * ( ABSEN.KELUAR - ABSEN.MASUK ) < 0 THEN 0
ELSE ( 24 * 60 ) * ( ABSEN.KELUAR - ABSEN.MASUK )
END
I don't think you can write such a subquery in Oracle. You should maybe checkout the update statement as its defined in the oracle documentation, here http://docs.oracle.com/cd/B19306_01/appdev.102/b14261/update_statement.htm
Having said that, what do you really want to do here? What value and under which conditions do you want to assign to the column LM?
That query doesn't look so good, in my opinion. You're trying to build a temporary table from the data stored in table_a and update that same table_a with values from that temporal table... but how? With the maximum of the temporal table? With the value of the same register when the condition is met?
I don't see how that query could work in MySQL either to be honest.
To sum up, could you provide additional info?
[EDIT] Just saw the modification in the question. You can remove the subquery from where it is and place it in the where statement...
UPDATE TABLE_A
SET TABLE_A.LM = TABLE_A.VALUE + (SELECT VALUE AS VAL FROM TABLE_A WHERE ID = 2)
WHERE TABLE_A.ID = 1

Multiply in update subquery select

I'm trying to update a table based on 2 select subquery that will be multipied to produce the value for Harga column
here is my code :
UPDATE bahanmakanan
SET Harga = (SELECT HargaSatuan from detail_bahanmakanan
WHERE IDBahanMakanan = "BM01")* (SELECT jumlah from bahanmakanan
WHERE IDBahanMakanan = "BM01")
WHERE IDBahanMakanan = "BM01" ;
The error message return
Error Code: 1093. You can't specify target table 'bahanmakanan' for update in FROM clause
you can simply do this using JOIN,
UPDATE bahanmakanan a
INNER JOIN detail_bahanmakanan b
ON a.IDBahanMakanan = b.IDBahanMakanan
SET a.Harga = a.jumlah * b.HargaSatuan
WHERE a.IDBahanMakanan = 'BM01'
Please do backup first your database before executing the statement.
Try this:
UPDATE bahanmakanan as t1
JOIN detail_bahanmakanan as t2 USING(IDBahanMakanan)
SET t1.Harga = t2.HargaSatuan * t1.jumlah
WHERE IDBahanMakanan = "BM01";