Postgres UPDATE with CASE and RETURNING - sql

I am trying to update columns using CASE statement
access_status here is an ENUM type, so, I have to CAST it otherwise Postgres gives error of converting text to ENUM with CASE statement (without CASE statement, I don't get this error)
UPDATE table_1
SET
access_status =
CASE
WHEN access_status='ACTIVE' THEN 'REVOKED'
ELSE access_status -- need to write this otherwise the value is set to NULL
END::access_status,
updated_at =
CASE
WHEN access_status='ACTIVE' THEN NOW()
ELSE updated_at
END,
updated_by =
CASE
WHEN access_status='ACTIVE' THEN 1
ELSE updated_by
END
WHERE
id = 4
RETURNING
id
From above, the condition is on single column only. I need to update multiple columns when access_status='ACTIVE' else DO NOTHING.
Also, I am RETURNING id to know if the update has been performed or not (to return response accordingly from the API). Want to return id only if the update has been performed
Is it possible to do it something like this =>
UPDATE table_1
CASE
WHEN access_status = 'ACTIVE' THEN SET access_status = 'REVOKED',
updated_by = 1,
updated_at = NOW()
END
WHERE
id = 4
RETURNING
id
So that, I don't need to write multiple CASE statements for each column update

Related

how to check if existing column changes from some value to NULL using Oracle

I'd like to check the following condition using sql query using Oracle:
to check id a user changes Condition from some value to another value
to check if a user changes condition from some value to NULL
I am trying for the below query:
(select count(*) from MyTable where (:userconditionid = (select condition_id from MyTable
where item = :useritem))
and item = :useritem)
where :userconditioncode is the value user is trying to enter value, the above query works for normal values but it wont work for null value , if user changes the condition from some value to null value
the above sql query fails.
Sample Data and Desired Results
If user is trying to alter the condition_id to NULL
then I have to throw am error as follows:
"User are not allowed to change the value to null"
also if user is trying to alter the condition from NULL to some other value
then it should not throw an error.
If I correctly got all your comments - the only case to throw error for you is when not-null value is tried to be changed to null. Consider using
select case when condition_id is not null and :userconditionid is null then 1 else 0 end as do_throw_error
from MyTable
where item = :useritem
in this case.
The thing about nulls is that almost all '=' comparisons to null return false.
The proper test is not '=' but 'is null':
In P/L SQL:
if :userConditionCode is null then
throw...
or is SQL:
(select count(*) from MyTable
where
(
(:userconditionid = (select condition_id from MyTable
where item = :useritem)
)
or :userconditionid is null
)
and item = :useritem)
The only way to check the value for null in SQL is IS NULL predicate. Of course, you can translate null to something else but real NULL check is nothing else than IS NULL.
Does this code suits your need? You've not wrote what should be done when there's no data for requested :useritem.
select 'User are not allowed to change the value to null' as msg
from MyTable
where item = :useritem
having (
min(1) /*Table has that item*/,
min(case
when f.condition_id is not null and :userconditionid is null
then 1
end) /*User sets non null value to null*/
) in ((1,1))

SQL assign the value to the column based on value in the first column

I am working with a dataframe that has 2 columns. Name and Type. I want to write a sql query that would check the values in the column "name" and based on the result will assign the value "direct" or "inderect" to the column "type"
sum(CASE when `Name` LIKE '%| R |%'
then `type` = 'Indirect'
else `type` = 'Direct'
end
)
But this doesn't work.
I guess, you need an update statement instead of a single case statement -
UPDATE YOUR_TAB
SET `type` = CASE WHEN `Name` LIKE '%| R |%' THEN 'Indirect'
ELSE 'Direct'
END
-- WHERE CLAUSE IF NEEDED.

merge condition is not working in sql server

I have two tables one is (providerLoc) and another one is (tmpProviderLoc) I need to take three columns combination from tmpProviderLoc and need to check the records exist in ProviderLoc
Case 1 : If record exist in providerLoc i need to update another column(Npi) in providerLoc based on column (npi) in tmpProviderLoc
case 2 : if not exist i need to insert the values in providerLoc
for that I have written below query:
MERGE INTO [dbo].[ProviderLoc] AS PL
USING
(
select *
from (
select *,
row_number() over (partition by [Location_ID],[PProviderTaxID]
,[POBOXZIP] order by [Location_ID],[PProviderTaxID],[POBOXZIP]) as row_number
from [dbo].[TmpProviderLoc]
) as rows
where row_number = 1
) AS TPL
ON TPL.[Location_ID] = PL.[ecProviderID]
AND TPL.[PProviderTaxID] = PL.[TaxID]
AND TPL.[NPI] = PL.[NPI]
AND TPL.[POBOXZIP] = PL.[POBOXZIP]
WHEN MATCHED THEN
UPDATE SET PL.[NPI] = CASE
WHEN TPL.[NPI] = NULL THEN PL.[NPI]
ELSE TPL.[NPI]
END
WHEN NOT MATCHED THEN
INSERT (EcProviderID,TaxID,NPI,POBOXZIP,ProviderLocationStatusID,CreatedON)
VALUES (TPL.[Location_ID],TPL.[PProviderTaxID],TPL.[NPI]
,TPL.[POBOXZIP],1,GETDATE());
But I am failing in updating the NPI value -- if npi value is new in tmpProviderLoc it is not updating in ProviderLoc..
Could any one please look into this issue..
or any other way to go through this kind of checking
The equal symbol in this is incorrect: WHEN TPL.[NPI] = NULL THEN PL.[NPI]
Use IS NULL
WHEN TPL.[NPI] IS NULL THEN PL.[NPI]
NULLs are special. They are "indeterminate" so they cannot be equal or unequal to anything purely because they just cannot have any value "determined". NULLs are the absence of value and equal/unequal does not apply.
To discover if NULL exists use IS NULL - or - IS NOT NULL to discover if there is a non-null value.

SQL case-when-else statement efficiency

When I use this statement;
UPDATE TABLE
SET FIELD = CASE
WHEN NAME = 'a' THEN (SELECT NO FROM TABLE_TWO WHERE NAME = 'a')
ELSE 'x' END
WHERE FIELD_TWO = 1
if TABLE.NAME != 'a' will the select SQL executed nevertheless?
Moreover, a little extra question, do you think it is proper to have such logic in SQL code for any given product? I think having any logic in SQL makes its coverage very difficult, and hard to maintain, what do you think?
edit: select statement only returns a single value, ignore the case where it can return multiple values, that case is not in the scope of this question.
The Oracle manual claims that it does short-circuit evaluation:
Oracle Database uses short-circuit evaluation. For a simple CASE expression, the database evaluates each comparison_expr value only before comparing it to expr, rather than evaluating all comparison_expr values before comparing any of them with expr
In your case comparison_expr is the WHEN NAME = 'a' part and if the manual is right, the database will not run the select if name has a different value.
I think it would be easier to read and maintain, when you split it into two UPDATE-statements like this:
UPDATE TABLE SET FIELD = (SELECT TOP 1 NO FROM TABLE_TWO WHERE NAME = 'a')
WHERE FIELD_TWO = 1
AND NAME='a'
UPDATE TABLE SET FIELD = 'x'
WHERE FIELD_TWO = 1
AND NAME != 'a'
It lets you add more cases easily and you can generalize the cases if there are more of them, like:
UPDATE TABLE SET FIELD = (SELECT TOP 1 NO FROM TABLE_TWO WHERE NAME = TABLE.FIELD)
WHERE FIELD_TWO = 1
AND NAME IN ('a','b','c')
If I were you, I would use a variable so that case doesn't compute a scalar value everytime. Something like following:
DECLARE #myVar VARCHAR(10);
SELECT TOP 1 #myVar = NO FROM TABLE_TWO WHERE NAME = 'a';
UPDATE TABLE
SET FIELD = CASE
WHEN NAME = 'a' THEN #myVar
ELSE 'x' END
WHERE FIELD_TWO = 1

Updating multiple columns using Case

I have a query that looks like below:
UPDATE some_table
SET column_x = CASE WHEN x_specific_condition THEN new_value_for_x ELSE column_x END,
column_y = CASE WHEN y_specific_condition THEN new_value_for_y ELSE column_y END,
WHERE some_more_conditions
Problem with above is, each column (x, y) still gets updated with their own value if some_more_conditions return true irrespective of their specific conditions returning true. I tried removing ELSE from above, but no luck
I am combining as some_more_conditions are same for both cases, I think its better to perform all in 1 update (suggestions welcome)
Do you know if there is a way that I can perform the above update in 1 query by skipping the individual columns where the specific conditions do not match (basically avoid overwriting of same values)
To do this in one update, you would need to expand the where clause:
UPDATE some_table
SET column_x = CASE WHEN x_specific_condition THEN new_value_for_x ELSE column_x END,
column_y = CASE WHEN y_specific_condition THEN new_value_for_y ELSE column_y END,
WHERE some_more_conditions AND
(x_specific_condition OR
y_specific_condition
);
An alternative is to use multiple updates, but that could be more expensive:
UPDATE some_table
SET column_x = new_value_for_x
WHERE some_more_conditions AND x_specific_condition;
UPDATE some_table
SET column_y = new_value_for_y
WHERE some_more_conditions AND y_specific_condition;
update [table_name]
set [column_name_1] = case when [column_name_1] = [condition_1] then [condition_2]
else [column_name_1]
end,
[column_name_2] = case when [column_name_2] = [condition_1] then [condition_2]
else [column_name_2]
end,
where condition;
Note: [table_name] is your table name, [column_name] is your column name in which you want to update values.
you can update values without where condition as well.
find screenshot