Snowfalke sql update if exists else insert - sql

I have looked at other question but seems that snowflake doesn't support if/else in sql, at least not the way that other sql servers support it.
some suggested to use javascript but i would like to avoid that if I can.
I am trying to Insert into a table using snowflake python library some data, if it's already there then I would like to update the data, I have looked at merge but it doesn't seem to fit me since my data isn't a table
that's what I have so far that isn't working
f"""BEGIN
IF (EXISTS (SELECT * FROM {self.okr_table} WHERE kpi=TRUE AND Month(month)=MONTH(current_date()) AND year(month)=YEAR(current_date())))
THEN
UPDATE {self.okr_table} SET [DATA] = {json.dumps(self.data)} WHERE kpi=TRUE AND Month(month)=MONTH(current_date()) AND year(month)=YEAR(current_date()))
ELSE
INSERT INTO {self.okr_table} (month, data, kpi) SELECT current_date(),parse_json('{json.dumps(self.data)}'), true;
END"""

To perfrom INSERT/UPDATE it is better to use single MERGE statement
I have looked at merge but it doesn't seem to fit me since my data isn't a table
It is not an issue as source could be a table or subquery:
MERGE INTO {self.okr_table}
USING (SELECT PARSE_JSON({json.dumps(self.data)} AS data
, MONTH(current_date()) AS month
, YEAR(current_date()) AS year
) s
ON {self.okr_table}.KPI
AND MONTH({self.okr_table}.month) = s.month
AND YEAR({self.okr_table}.month) = s.year
WHEN MATCHED THEN UPDATE
WHEN NOT MATCHED THEN INSER ...;
IF/ELSE branching works in Snowflake:
BEGIN
IF (EXISTS (...)) THEN
UPDATE ... ;
ELSE
INSERT ... ;
END IF;
END;
Please note ; after each statement, END IF and parenthesis around condition.

Related

Taking out bypass_ujvc hint in 12c converting update to merge statements

Hi I've been tasked with getting rid of the bypass_ujvc hint from a number of update statements as it's no longer supported in Oracle 12c, I have decided to replace the update statements with a merge statement, unluckily one of these update statements has a returning clause and a bulk collect, so i'm unsure how to approach this as a merge statement does not use a returning clause. Any advice is much appreciated. The query is below.
UPDATE /*+ bypass_ujvc */ (SELECT caco.surr_id,
caco.lead_item_yn,
caco.case_reference,
caco.logically_deleted_y
FROM TABLE (CAST(l_cc_surr_id AS db_surr_id_type_tab)) cc
JOIN case_contexts caco ON (caco.cc_surr_id = cc.COLUMN_VALUE)
JOIN cases cas ON (cas.REFERENCE = caco.case_reference )
WHERE caco.logically_deleted_y IS NULL
AND cas.status IN ('INP', 'TOS'))
SET logically_deleted_y = 'Y'
RETURNING surr_id, lead_item_yn, case_reference
BULK COLLECT INTO l_caco_surr_id, l_lead_item, l_all_cases;
An approach using bulk collect and forall would look something like this:
begin
select caco.surr_id, caco.lead_item_yn, caco.case_reference
bulk collect into l_caco_surr_id, l_lead_item, l_all_cases
from table(l_cc_surr_id) cc
join case_contexts caco on caco.cc_surr_id = cc.column_value
join cases cas on cas.reference = caco.case_reference
where caco.logically_deleted_y is null
and cas.status in ('INP', 'TOS');
forall i in 1..l_caco_surr_id.count
update case_contexts
set logically_deleted_y = 'Y'
where surr_id = l_caco_surr_id(i);
end;
You might want to put that in a loop with a limit clause, but this should give the general idea.

Merge statement for first time insert

I did some research and couldn't find any solution and hence posting it here.
We have a dataload job which runs on a daily basis. We have separate DML statements to insert, update etc. We wanted to avoid insert statements to run multiple times.
Is there an option to use merge statement in this scenario to update if the record is present or insert if not present?
Please give me an example if possible as I am quite new to sql statements.
We are using Oracle db2 for dbms
Thanks in advance!
Use an IF EXISTS statement, like this:
IF EXISTS (SELECT 1 FROM #mytable# WHERE #column1# = #this# AND #column2# = #that)
BEGIN
#update statement#
END
ELSE
BEGIN
#insert statement#
END
EDIT:
the syntax for this can be found here: https://www.toadworld.com/platforms/ibmdb2/w/wiki/7777.ifthenelse
this means that my general case would become this in DB2:
IF (#count of value# = 1) THEN
#updatestatement#;
ELSEIF (#count of value# > 1) THEN
#throw an error, as you cannot update uniquely#
ELSE
#insertstatement#;
END IF;
I also noticed that you can run SQL commands on DB2, which might be useful for this task as well
finally, have a look here, might give you further ideas :)
DB2 for IBM iSeries: IF EXISTS statement syntax
Got it done throught Merge statements itself :)
MERGE INTO table1(storeent_id, name, value) AS t1
USING (VALUES ((SELECT STOREENT_ID FROM STOREENT WHERE IDENTIFIER='test'), 'SOLR_SERVICEABILITY_URL',
'Sample')) AS t2(storeent_id, name, value)
ON t1.name = t2.name AND t1.storeent_id = t2.storeent_id
WHEN MATCHED THEN
UPDATE SET
t1.value = t2.value
WHEN NOT MATCHED THEN
INSERT
(name, storeent_id, value)
VALUES (t2.name, t2.storeent_id, t2.value);

Convert SQL to PL/SQL For "IF NOT EXISTS"

I have some SQL code that I want to convert into PL/SQL for Oracle, however I'm struggling to find a good alternative for the "IF NOT EXISTS" function. Can someone help?
Here's the SQL that needs converting:
IF NOT EXISTS (SELECT * FROM SEC_ConfigSetting WHERE ItemKey='Version')
BEGIN
INSERT INTO SEC_ConfigSetting
([VersionNo]
,[Section]
,[ItemKey]
,[ItemValue]
,[ItemType])
VALUES
(1,4,'Version','V1.4.0',0)
END
ELSE
BEGIN
/* Update database version */
UPDATE [SEC_ConfigSetting]
SET [ItemValue] = 'V1.4.0'
WHERE ItemKey='Version'
END
What you're doing looks like you need merge
merge into SEC_ConfigSetting s
using (select 1 VersionNo, 4 Section,'Version' ItemKey,'V1.4.0' ItemValue, 0 ItemType from dual) d
on (s.ItemKey = d.ItemKey)
when matched then update set
ItemValue = d.ItemValue
when not matched then
INSERT (VersionNo, Section,ItemKey,ItemValue,ItemType)
VALUES (d.VersionNo, d.Section, d.ItemKey, d.ItemValue, d.ItemType);
And this can be used as a plain SQL or as part of PL/SQL script.

Testing For Primary Key Existence In Oracle SQL Trigger

I'm trying to write a trigger within SQL, and the code within needs to determine whether an entry exists in the table before either attempting to update, or insert.
I have tried using both
IF EXISTS
UPDATE
ELSE
INSERT
And
UPDATE
IF ##ROWCOUNT = 0
INSERT
But neither of them work. I'm partial to using the latter because my employer is nuts about efficiency (well...duh...) For this reason I'm also reluctant to use
IF SELECT COUNT(*) = 0
UPDATE
ELSE
INSERT
Does anybody know any ways to get around this?
--
UPDATE: I am trying to use MERGE, but I am receiving several errors...
MERGE INTO [tableName] AS Target
USING (SELECT :NEW.PIDM) AS Source (PIDM)
ON (Target.PIDM = Source.PIDM)
WHEN MATCHED THEN
[UPDATE STATEMENT]
WHEN NOT MATCHED THEN
[INSERT STATEMENT]
This gives me an error complaining that I'm missing the 'USING' keyword, as well as another complaining about the WHEN statement...
Use MERGE instead
In PL/SQL, you would use SQL%ROWCOUNT instead of ##ROWCOUNT:
UPDATE (...);
IF SQL%ROWCOUNT = 0 THEN
INSERT (...);
END IF;
Or, you could use SQL%NOTFOUND, which I personally think is easier to understand the intent:
UPDATE (...);
IF SQL%NOTFOUND THEN
INSERT (...);
END IF;
As for the MERGE command, the Oracle syntax is slightly different from the SQL Server which #zerkms linked to. In particular, you should leave the word "AS" out of the table alias, and you shouldn't list columns after the "USING" clause. Also, in Oracle SQL, the FROM clause is mandatory. You can use the DUAL table to mimic SQL Server's behavior. Putting it all together (this is untested):
MERGE INTO tableName Target
USING (SELECT :NEW.PIDM FROM DUAL) Source
ON (Target.PIDM = Source.PIDM)
WHEN MATCHED THEN
[UPDATE STATEMENT]
WHEN NOT MATCHED THEN
[INSERT STATEMENT]

Sql update statement, any way of knowing what it actually did?

Typically, I test an update by running a query using the where statement and then after verifying that it does what I think I want it to copying the where clause to the update statement and executing it. But is there any way of getting the statement to return what the update did besides the '4 rows updated'
Sure, take a look at the output clause of T-SQL
http://msdn.microsoft.com/en-us/library/ms177564.aspx
You could load your records into a temp table/variable in SQL Server:
DECLARE #Temp TABLE(ID INT)
INSERT INTO #Temp (ID)
SELECT ID
FROM Customer
WHERE AcctBalance > 5000
--inspect as needed
UPDATE Customer
SET AcctBalance = 0
WHERE ID IN (SELECT ID FROM #Temp)
That depend in the server, library that you use, in php, pdo exec return number of row effected by delete or update cluase