Update table only if value does not exist in a specific column - sql

I want to update a column (variableA) in a table (myTable) only when
There is no dataset with this #variableA in the variableA column
There is already a dataset with #variableB in the variableB column and with 'DUMMY' in the variableA column
FYI: Another interface inserts the 'DUMMY' datasets before and I later need to update them with the real variables/numbers.
The code below is already working fine but I am wondering if there is a more "elegant" solution to do this. I want to avoid/change the last line ("SELECT COUNT(*)" etc.)
DECLARE #variableA nvarchar(10) = '12345'
DECLARE #variableB nvarchar(10) = '67890'
UPDATE TOP (1) myTable
SET variableA = #variableA,
timestamp = GETDATE()
WHERE variableB = #variableB
AND variableA = 'DUMMY'
AND (SELECT COUNT(*) FROM myTable WHERE variableA = #variableA) = 0
Can you please help me to find a smarter solution instead of this last line?

you can use not exists operator like this
not exists (SELECT 1 FROM myTable WHERE variableA = #variableA)
and if it again slow you can set index I_my_Table_variableA by your variableA column and it will be more faster(you can set index by variable because it almost unique and it will be good index)

Well, I would write it like this:
UPDATE myTable
SET variableA = #variableA,
timestamp = GETDATE()
WHERE variableB = #variableB
AND variableA = 'DUMMY'
AND NOT EXISTS (
SELECT 1
FROM myTable
WHERE variableA = #variableA
)
First, Using TOP without specifing ORDER BY is a mistake, since database tables are unsorted by nature, this actually means that you might get unexpected results.
Second, changing the (select count) > 0 to exists(select...) might improve performance (unless the optimizer is smart enough to use the same execution plan for both cases)
Also, for your future questions - Please avoid using images to show us sample data and desired results. Use DDL+DML to show sample data, and text to show desired results. If you do that, we can copy your sample data to a test environment and actually test the answers before posting them.

Related

Find multiple SQL columns and update based on defined data listed in query

I have an update query in which I am trying to locate data in a column from a single table. All while taking other defined data listed in the query to update another column in the same table once a match has been found with that original search. Below is an example of my update statement. My end goal is to find '003447710' then update AltId to '540112'
UPDATE Site
SET AltId = ('540112'
'540129'
'540142'
'540143')
WHERE CCMFStatus in ('003447710',
'002754540',
'003564370',
'005942870')
I am sure there may already be something like this out there but I am really having trouble on an easy method on how to do this quickly and accurately.
Try this
update site
set altid = a.altid
from
(select altid,CCMFstatus from site) as a
where site.CCMFstatus = a.CCMFstatus
The best way might be multiple update statements:
UPDATE Site
SET AltId = '540112'
WHERE CCMFStatus = '003447710';
And so on.
If not, you can do this with a giant case statement or a join:
WITH values as (
SELECT '003447710' as oldstatus, '540112' as newaltid UNION ALL
SELECT '002754540', '540129' UNION ALL
SELECT '003564370', '540142' UNION ALL
SELECT '005942870', '540143'
)
UPDATE s
SET AltId = va.newaltid
FROM site s JOIN
values v
ON s.CCMFStatus = v.oldstatus;
If you already have the values in a table, then you don't need the WITH statement. You can just use the table.
Have you tried using CASE statement?
UPDATE SITE SET AltID = (CASE
WHEN CCMFStatus = '003447710' THEN '540112'
WHEN CCMFStatus = '002754540' THEN '540129'
END)
WHERE
CCMFStatus in ('003447710', '002754540', '003564370', '005942870');
BR,

sql server if statement not working

Can anyone advise me as to what is wrong with the following SQL server update statement:
IF (SELECT * FROM TBL_SystemParameter WHERE code='SOUND_WRONG_GARMENT') = ''
GO
UPDATE TBL_SystemParameter
SET [Value] = 'Ping.wav'
WHERE ID = (SELECT ID
FROM TBL_SystemParameter
WHERE code = 'SOUND_WRONG_GARMENT')
You don't need an if statement - you can just run the update statement, and if the subquery returns no rows, no rows will be updated. The if won't really save anything - you're performing two queries instead of one.
You either want
UPDATE TBL_SystemParameter
SET [Value] = 'Ping.wav'
WHERE ID In (SELECT ID
FROM TBL_SystemParameter
WHERE code = 'SOUND_WRONG_GARMENT')
if there are multiple ID's with that code OR use
UPDATE TBL_SystemParameter
SET [Value] = 'Ping.wav'
WHERE code = 'SOUND_WRONG_GARMENT'
either way and lose the IF statement as #Mureinik said.
Although Mureinik's answer is the logical solution to this, I will answer why this isn't actually working. Your condition is wrong, and this approach will work instead using IF EXISTS:
IF EXISTS (SELECT * FROM TBL_SystemParameter WHERE code='SOUND_WRONG_GARMENT')
BEGIN
UPDATE TBL_SystemParameter
SET [Value] = 'Ping.wav'
WHERE ID IN (SELECT ID
FROM TBL_SystemParameter
WHERE code = 'SOUND_WRONG_GARMENT')
END
As a side note, you're using an = sign instead of IN, which means you'll be matching to an arbitrary singular ID and only update 1 row based on this. To use a set based operation, use the IN clause.
You could actually 'golf' this by doing away with the derived query altogether, and using a simple WHERE code='SOUND_WRONG_GARMENT' on the table you're updating on.

Update a table from another table on multiple columns in Oracle 11g

Oracle 11g SQL & both tables have the same column definitions:
VARCHAR2(11)
NUMBER
DATE
DATE
I tried to find a solution to this problem, and this is what I ended up with, which fails:
update jjjTable
set [fourthCol] = B.[fourthOtherCol]
from jjjTable, otherTable B
where jjjTable.[firstCol] = B.[firstOtherCol]
and jjjTable.[secondCol] = B.[secondOtherCol]
and jjjTable.[thirdCol] = B.[thirdOtherCol]
I'm under the impression that I need to have the from in this was based on this article:
SQL update from one Table to another based on a ID match and the edited response from Shivkant
I'm under the impression that I may need to use a join based on this article:
How do I UPDATE from a SELECT in SQL Server? and the response from Robin Day
but as I understand it, joins are only on one column match per row. I'm interested in matching on 3 elements, and I'm not finding a clear path for solution.
Any direction would be well received.
This is what I ended up needing to do as a solution:
DECLARE
CURSOR j_CUR IS
SELECT A.[fourthCol]
FROM JJJtable A, otherTable B
WHERE A.[firstCol] = B.[firstOtherCol]
and A.[secondCol] = B.[secondOtherCol]
and A.[thirdCol] = B.[thirdOtherCol]
FOR UPDATE OF B.[fourthOtherCol];
SOME_DATE DATE;
BEGIN
FOR IDX IN j_CUR LOOP
SOME_DATE :=(IDX.[fourthCol]);
UPDATE otherTable
SET [fourthOtherCol] = SOME_DATE
WHERE CURRENT OF j_CUR;
END LOOP;
END;
Thank you for your efforts and guidance.
This is the close best I was able to get it to work on my similar use case. Try this out.
update jjjTable
SET jjjTable.[fourthCol] = (SELECT distint otherTable.fourthOtherCol from otherTable
WHERE otherTable.firstOtherCol = jjjTable.firstCol and
otherTable.secondOtherCol = jjjTable.secondCol and
otherTable.thirdOtherCol = jjjTable.thirdCol)
WHERE EXISTS (SELECT distint otherTable.fourthOtherCol from otherTable
WHERE otherTable.firstOtherCol = jjjTable.firstCol and
otherTable.secondOtherCol = jjjTable.secondCol and
otherTable.thirdOtherCol = jjjTable.thirdCol);

Updates which include auto increment column

I am using PostgreSQL and I would like to update a table which would include an auto number column id. I know it might something very simple but I have done something like this;
CREATE SEQUENCE SEQ_ID
MINVALUE 1
START WITH 1
INCREMENT BY 1
CACHE 10
update trk2
set (id, track_id, track_point) =
(select nextval('seq_id'), trk1.track_fid, trk1.wkb_geometry
from track_points_1 as trk1
where track_fid = 0)
The thing is that it is giving me the following error (code reformatted):
ERROR: syntax error at or near "select"
LINE 3: set (id, track_id, track_point)=(select nextval('seq_id'), t...
Can anybody help please?
Your query is broken in several places. It could look something like this:
UPDATE trk2
SET (id, track_id, track_point) =
(next_id, x.track_fid, x.wkb_geometry)
FROM (
SELECT id
,nextval('seq_id') AS next_id
,track_fid
,wkb_geometry
FROM track_points_1
WHERE track_fid = 0
) x
WHERE trk2.id = x.id; -- adapt to your case
Or simpler (preferable syntax):
UPDATE trk2
SET (id, track_id, track_point) =
(nextval('seq_id'), x.track_fid, x.wkb_geometry)
FROM track_points_1 x
WHERE x.track_fid = 0
AND trk2.id = x.id; -- adapt to your case
Major points:
An UPDATE without a WHERE clause only makes sense if you really need to change each and every row in the table. Else it is wrong or at least sub-optimal.
When you retrieve values from another table, you get a CROSS JOIN between target and source if you don't add a WHERE clause connecting target with source - meaning that every row of the target table will be updated with every row in the source table. This can take a very long time and lead to arbitrary results. The last UPDATE wins. In short: this is almost always complete nonsense and extremely expensive at that.
In my example I link target and source by the id column. You have to replace that with whatever fits in your case.
You can assign multiple values in one SET clause in an UPDATE, but you can only return a single value from a correlated subselect expression. Therefore, it is strictly not possible to have a subselect in a SET clause with multiple values.
Your initial syntax error comes from a missing pair of parenthesis around your subselect. But adding that only reveals the error mentioned above.
Depending on what you are after, you would include nextval('seq_id') in the subquery or in the SET clause directly. This can lead to very different results, especially when you have rows in the subquery that are not used in the UPDATE.
I placed it in the SET clause because I suspect, that's what you want. The sequence of rows is still arbitrary. If you want more control over which numbers are assigned, you need to define what you want and then take a different route.
Tyler Eaves is correct, this action is not advisable.
However, if you insist, this may help:
Once you have a sequence on a column you don't have to call nextval() in the SET statement. Just leave it out and the column will auto-increment.
UPDATE
trk2
SET
(
track_id = [track_id Value],
track_point = [track_point Value]
)
or, include it and set it to default or null
UPDATE
trk2
SET
(
id = default,
track_id = [track_id Value],
track_point = [track_point Value]
)
Using your example:
UPDATE
trk2
SET
(
track_id,
track_point
) = (
SELECT
trk1.track_fid,
trk1.wkb_geometry
FROM
track_points_1 AS trk1
WHERE
track_fid = 0
)
I think you need a second set of parentheses on the RHS of the SET clause:
UPDATE trk2
SET (id, track_id, track_point) =
((SELECT nextval('seq_id'), trk1.track_fid, trk1.wkb_geometry
FROM track_points_1 as trk1
WHERE track_fid = 0));
The first set of parentheses matches the parentheses on the LHS of the SET clause. The second set wraps up the sub-query for re-use.

Updating a table within a select statement

Is there any way to update a table within the select_expr part of a mysql select query. Here is an example of what I am trying to achieve:
SELECT id, name, (UPDATE tbl2 SET currname = tbl.name WHERE tbl2.id = tbl.id) FROM tbl;
This gives me an error in mysql, but I dont see why this shouldn't be possible as long as I am not changing tbl.
Edit:
I will clarify why I cant use an ordinary construct for this.
Here is the more complex example of the problem which I am working on:
SELECT id, (SELECT #var = col1 FROM tbl2), #var := #var+1,
(UPDATE tbl2 SET col1 = #var) FROM tbl WHERE ...
So I am basically in a situation where I am incrementing a variable during the select statement and want to reflect this change as I am selecting the rows as I am using the value of this variable during the execution. The example given here can probably be implemented with other means, but the real example, which I wont post here due to there being too much unnecessary code, needs this functionality.
If your goal is to update tbl2 every time you query tbl1, then the best way to do that is to create a stored procedure to do it and wrap it in a transaction, possibly changing isolation levels if atomicity is needed.
You can't nest updates in selects.
What results do you want? The results of the select, or of the update.
If you want to update based on the results of a query you can do it like this:
update table1 set value1 = x.value1 from (select value1, id from table2 where value1 = something) as x where id = x.id
START TRANSACTION;
-- Let's get the current value
SELECT value FROM counters WHERE id = 1 FOR UPDATE;
-- Increment the counter
UPDATE counters SET value = value + 1 WHERE id = 1;
COMMIT;