Can I use DECODE in a UPDATE statement? - plsql

Can I use DECODE in a UPDATE statement on the left hand side of SET?
UPDATE temp SET DECODE(update_var, 1, col1,
2, col2) = update_value;
This is giving me error as eual sign ignored..

How about this? If the update flag is set to 1, col1 gets updated, if set to 2, then col2 gets updated.
UPDATE temp
SET col1 = DECODE(update_var, 1, update_value, col1),
col2 = DECODE(update_var, 2, update_value, col2)
Also, as a bonus, it'll handle the possible situation where the update variable is set to something other than one or two!

No you can't do that. You can do this in PL/SQL:
IF update_var = 1 THEN
UPDATE temp SET col1 = update_value;
else
UPDATE temp SET col2 = update_value;
END IF;
Or you could use dynamic SQL like this:
l_sql := 'UPDATE temp SET col'||update_var||' = :v';
EXECUTE IMMEDIATE l_sql USING update_value;

You cant use decode in an update statement.
You can however use a merge statement.
http://psoug.org/reference/merge.html
MERGE INTO temp b
USING (
SELECT key, DECODE(update_var, 1, update_value, col1) as col1,
DECODE(update_var, 2, update_value, col2) as col2
FROM temp
WHERE key =theKeyIPassedIn) e
ON (b.key = e.key)
WHEN MATCHED THEN
UPDATE SET b.col1 = e.col1, b.col2 = e.col2
;
Basically you are using the select portion of the merge to decode col1 and col2 to either the update_value or the value that exists already.
This may also be too verbose for your needs, and the solution that uses an if statement or execute immediate may better suit your problem.

Related

check for null values in all columns of a table using SQLite

I have a table with more than 15 columns. 2 of of them are of the type varchar, and most of them of type int and float.
I am new to SQL and am trying to figure out a way by which I can check if any of the columns have a NULL value in it.
Had there been just 4 or 5 columns I could have checked them individually with
SELECT COUNT(*) FROM table_name WHERE col1 IS NULL OR col2 IS NULL OR col3 IS NULL ...
But is there any efficient way to do this on a lot of columns in SQLite specifically?
I have referred to other questions regarding this here but I cannot use xml or store anything. Also I am using SQLite and can only run a query.
There is no way (that I know of) to check all columns if they contain null without explicitly listing all the column names.
Your query is the proper way to do it.
If you want to shorten (not significantly) the code you could use these alternatives:
SELECT COUNT(*) FROM table_name WHERE col1 + col2 + col3 IS NULL;
or:
SELECT COUNT(*) FROM table_name WHERE col1 || col2 || col3 IS NULL;
or:
SELECT COUNT(*) FROM table_name WHERE MAX(col1, col2, col3) IS NULL;
The above queries work, for any data type of the columns, because if there is even only 1 column equal to null then addition, concatenation and the scalar function MAX() (and MIN()) all return null.
See the demo.

Eliminate ID if Col2 = (1,2,3)

I am using teradata sql, and I have the following input
If col2 has (1,2,3) values then delete the Id from table, so my desired table is:
I tried all possible ways, but cannot get to eliminate the IDs? Any help or suggestion will help. thanks
DELETE FROM yourTable
WHERE Id IN ( SELECT Id FROM yourTable WHERE col2 IN (1,2,3) )
If you actually want to delete those IDs you better use #MudassirHasan's solution, but if you want to select the other IDs you can utilize Conditional Aggregation in a Group Max:
select *
from mytable
qualify
max(case when col2 (1,2,3) then 1 else 0 end) -- will return zero when those values don't exist
over (partition by id) = 0 -- for an ID

Can anyone guide me how to achieve below scenario

I have source and target tables with some calculation as I mentioned below, I want to populate result set of the calculation from the source table into the destination table.
Columns in destination table are enabled NOT NULL constraint.
Can anyone guide me to achieve below requirement.
SOURCE TABLE:
Source_table1 >>
col1,
col2,
col3
Source_table2 >>
col1,
col2,
col3
TARGET TABLE:
Dest_table:
col1 >> Source_table1.col1+Source_table2.col1
col2 >> Source_table1.col2+Source_table2.col2
col3 >> Dest_table.col1+Dest_table.col2
col4 >> Source_table1.col3+Source_table1.col3+Dest_table.col3
Thanks in advance.
All you need is three layers of summations, something as shown below. A simple Insert into select should work than going for a PL/SQL block. And as per one of your comments, source_tab1.seq_no = source_tab2.seq_no is the join condition between the source tables.
INSERT INTO Dest_table (col1,
col2,
col3,
col4)
SELECT dcol1,
dcol2,
dcol3,
s1col3 + s2col3 + dcol3 dcol4
FROM (SELECT dcol1,
dcol2,
dcol1 + dcol2 dcol3,
s1col3,
s2col3
FROM (SELECT s1col1 + s2col1 dcol1,
s1col2 + s2col2 dcol2,
s1col3,
s2col3
FROM (SELECT s1.col1 s1col1,
s1.col2 s1col2,
s1.col3 s1col3,
s2.col1 s2col1,
s2.col2 s2col2,
s2.col3 s2col3
FROM source_table1 s1
JOIN source_table2 s2
ON s1.seq_no = s2.seq_no)));

RODBCext syntax examples for parameterized select queries with a subquery

I'm trying to find use RODBCext syntax for multiple parms in the same query with at least one of them part of an IN clause.
This is the approach I'm taking, but it doesn't like the IN part:
Error: unexpected symbol in "AND col2 "
This is how I'm specifying the parms:
prm <- data.frame( '2', c('B01', 'B12', 'B23', 'B34', 'B45'))
This is the SQL"
dataResult <- sqlExecute, connHandle, query = "
select col1, col2, col3
from tblA
where col1 = ?
and col2 IN ?
"
, prm
, fetch = TRUE)
odbcClose(connHandle)
I've looked at the CRAN pdf
and
the vignettes
I resolved this by changing the syntax to use OR rather than IN. This makes it harder to read, but the code runs successfully.

How to set unique constraint over multiple columns when any one can be null?

How do I set unique constraint over multiple columns when any one can be null in SQLite?
e.g. I have made unique("col1","col2","col3") and tried insert into tablename values("abc","def",null) twice it inserted both rows.
The unique constraint is not working when third column is null.
In sqlite, all null are differences.
I think the best way to solve this issue is to set column c not null with a special default value. Then use the default value (for example 0, '') to represent null.
edit 1
you can easily extend this solution to any columns
create table test (
a text not null default "",
b text not null default "",
c text not null default ""
);
You could create a trigger to enfore this:
CREATE TRIGGER col1_col2_col3null_unique
BEFORE INSERT ON MyTable
FOR EACH ROW
WHEN col1 IS NOT NULL
AND col2 IS NOT NULL
AND col3 IS NULL
BEGIN
SELECT RAISE(ABORT, 'col1/col2/col3 must be unique')
FROM MyTable
WHERE col1 = NEW.col1
AND col2 = NEW.col2
AND col3 IS NULL;
END;
You need such a trigger for each possible combination of NULLs in the three columns.
Furthermore, if it is possible to have UPDATEs that change such a column to NULL, you need triggers for those, too.
Starting with version 3.9.0 (2015-10-14) you can use indexes on expressions (https://www.sqlite.org/expridx.html) and use for example the COALESCE function to transform null values into some form of fallback value:
CREATE UNIQUE INDEX IX_Unique ON Table1 (
COALESCE(col1, ""),
COALESCE(col2, ""),
COALESCE(col3, "")
);

Resources