I have a table with several columns that allow NULLs. How would I go about writing a SQL Query that will allow me to skip that column in an update if the value is "empty". Should I use a boolean flag letting the query know to update that value? I do something similar in a SELECT like this
SELECT * FROM table WHERE (#boolFlag = 1 OR col1 = #col1Val)
But trying to do that for an update has proven to be an exercise in futility. Ideally I'd be able to say skip this value if true, otherwise update over my 20ish columns. Right now I can't pass in DBNull.Value, so instead I'm being forced to insert "" which is converted into whitespace (for instance, my nvarchar(50) has 50 spaces).
I'm using a SQL Server DB/Table and a DataSet in VB.NET, constructing my queries in VS2k8 if that matters.
You could do:
update MyTable
set MyColumn = case when #MyColumnValue = '' then null else #MyColumnValue end
A short form of the above would be:
update MyTable
set MyColumn = case when #MyColumnValue <> '' then #MyColumnValue end
Related
I have the following column, B represents boolean and the rest are empty values. I have to change all the values in this column to the word COLUMN A.
COLUMN
-----
B
I have tried different things, for example
SELECT COLUMN
FROM TABLE
WHERE COALESCE(NULLIF(COLUMN,''), 'COLUMN A');
And I receive the error: "Invalid character found in a character string argument of the function "BOOLEAN"." I'm kind of stuck to this question and I'm getting confused with this boolean value. I will be really happy if someone can help me, thanks!
The easiest thing is to use CASE expression. I am not familiar in db2, so you may want to research it further, but in other DBMSs it works like this:
SELECT CASE
WHEN COLUMN = '' THEN 'COLUMN A' -- if COLUMN = '', replace it with 'COLUMN A'
ELSE COLUMN -- otherwise, keep COLUMN as is.
END as 'COLUMN' -- name the column in the result 'COLUMN'
FROM TABLE
This is an article that explains how it works in db2:
https://www.ibm.com/support/knowledgecenter/en/SSEPEK_11.0.0/sqlref/src/tpc/db2z_caseexpression.html
The WHERE clause is unfinished. Compare the COALESCEd value to something:
SELECT COLUMN
FROM TABLE
WHERE COALESCE(NULLIF(COLUMN,''), 'COLUMN A') = 'COLUMN A';
Or better:
SELECT COLUMN
FROM TABLE
WHERE COLUMN IS NULL OR COLUMN = ''
Doesn't require any thinking/calculating to work out your selection logic. More maintainable, nicer for peer developers
*The above is generic advice for usual cases NOT involving boolean datatypes (which typically require some different treatment)
Now, you say you have to change the value to something. That requires an UPDATE statement. If this column is a boolean then it won't have a value of empty string. The blanks will be nulls:
UPDATE TABLE SET COLUMN = (some boolean) WHERE COLUMN IS NULL
If you don't want to permanently change the table data to something, but instead want to select it out as some value where a blank occurs, but keep the blanks stored in the table:
SELECT COALESCE(column, (some boolean)) FROM TABLE
Might be worth noting that not all versions of DB2 can return a boolean in a result set - this is quite typical of database vendors. Convert the boolean to something else representable using a case when, if your DB2 version is thus restricted
SELECT CASE WHEN column = TRUE THEN 'true' ELSE 'false' END FROM TABLE
If I wanted to move data from one field into another field within the same record and then remove the data from the existing field can this reliably be done in one SQL statement, and is this dependent on the Database Provider?
An example of the SQL I am thinking about is below
UPDATE table SET field2 = field1, field1 = '' WHERE keyField = 1
Thanks for any help
Yes, it is reliable because major DB's like Oracle, SQL Server, MySQL, etc. are transactional, which ensure ACID. In other words, it's an all-or-nothing scenario, all changes happen or non happen (if a transaction is rolled-back for example).
However it is not sequential; i.e. doing this would yield the same result:
UPDATE table SET field1 = '', field2 = field1 WHERE keyField = 1
Rather, your SQL is doing something like this:
UPDATE table
SET field2_NewValue = field1_OriginalValue
, field1_NewValue = ''
WHERE keyField = 1
I wanted to update 1 column from a table present in a database maintained in SQL 2008 R2.
The entire column contains same value of data type int and I want to change to different value of same int data type.
When do we use single apostrophe in SET statement & when to avoid or not use it?
UPDATE TABLENAME
SET COLUMNNAME = X
OR
UPDATE TABLENAME
SET COLUMNNAME = 'X'
Appreciate any suggestions/advise. Thanks.
In SQL, single quotes are used around string values. Other "values", like integers, references to other columns etc, should never be single quoted.
I'm trying to update multiple rows using postgres, I'm using this code:
UPDATE foobar SET column_a = CASE
WHEN column_b = '123' THEN 1
WHEN column_b = '345' THEN 2
END;
If I create a new table this works flawlessly, but when running this on a large table with 8 million rows this hangs indefinitely. I've tried first in Admineer (web interface) and also in console.
However this works just fine:
UPDATE foobar SET column_a=1 WHERE column_b='123';
I'm hesitant to implement this approach into my code since I'll have thousands of updates at once and would prefer to put them in one statement. Any ideas as to why the first example would hang postgres and the second would work just fine? I just double checked and I have no rules applied on the table.
The problem was ..
The statement:
CASE
WHEN column_b = '123' THEN 1
WHEN column_b = '345' THEN 2
END;
.. is just short for:
CASE
WHEN column_b = '123' THEN 1
WHEN column_b = '345' THEN 2
ELSE NULL
END
Meaning, without a WHERE clause, your UPDATE statement is not just "trying", it actually updates every single row in the table, most of them to NULL.
Maybe, a NOT NULL constraint on the column prevented data loss ...
The better solution is ..
I'll have thousands of updates at once and would prefer to put them in one statement.
Much faster (and shorter) for large sets:
UPDATE foobar f
SET column_a = val.a
FROM (
VALUES
(123, 1)
,(345, 2)
) val(b, a)
WHERE f.column_b = val.b
Joining to a set beats iterating through a long list of CASE branches for every row easily. The difference will grow rapidly with longer lists.
Also, be sure to have an index on column_b either way.
You can replace the VALUES expression with any table, view or subselect yielding appropriate rows.
Note:
I am assuming that column_a and column_b are of type integer. In this case, the single quotes around '123' in your question were never helpful. You'd better use a numeric literal instead of a string literal. (Even though it works with string literals, too.)
A string literal like '123' defaults to unknown type.
A numeric literal like 123 defaults to integer - or bigint / numeric if the number is too big.
If you were dealing with non-default data types, you would have to cast explicitly. Would look like:
...
FROM (
VALUES
('123'::sometype, '1'::sometype) -- first row defines row type
,('345', '2')
) val(b, a)
...
I'm keeping this question up in case anyone runs into this issue.
This query was the culprit:
UPDATE foobar SET column_a = CASE
WHEN column_b = '123' THEN 1
WHEN column_b = '345' THEN 2
END;
Problem is that it's missing a WHERE statement so it's trying to update all rows. With large databases this can be an issue, in my case it just timed out. As soon as I added the where statement in there it fixed the issue.
Here's the solution:
UPDATE foobar SET column_a = CASE
WHEN column_b = '123' THEN 1
WHEN column_b = '345' THEN 2
END
WHERE column_b IN ('123','345')
Can someone set me straight on the correct syntax for this statement?
I am trying to update a new field in table rounds with an average of a field in table holes where rounds.id is stored as a foreign key.
UPDATE `rounds` SET drivingDistance_avg_per_hole =
SELECT SUM(holes.drivingDistance)/COUNT(holes.drivingDistance) as avg
FROM `holes`, `rounds`
WHERE holes.drivingDistance != ''
AND holes.round = rounds.id
Sure would appreciate the lesson!
Depends on your database. Standard SQL doesn't have the FROM syntax with UPDATE and some databases don't support it. In that case this ought to work:
UPDATE `rounds` SET drivingDistance_avg_per_hole = (
SELECT SUM(holes.drivingDistance)/COUNT(holes.drivingDistance) as avg
FROM `holes`
WHERE holes.drivingDistance != ''
AND holes.round = rounds.id )
The key points are that the subselect has to be in parentheses, and that you don't want to include the destination table in the subselect because then you're selecting all rows of the table whereas you only care about the rows of holes that match the corresponding row from rounds.