Error when using INSERT INTO inside CASE statement - sql

I'm trying to insert values into a table inside a CASE statement, but I'm getting the error "missing expression" in my INSERT INTO.
What is the correct way to use INSERT INTO within CASE? You can find the code below. I am using this SELECT statement in a procedure, and I'm putting the result of this into a cursor.
SELECT
COALESCE(a.file_type,b.file_type) AS file_type,a.input AS a_input,b.input AS b_input,a.output AS a_output,b.output AS b_output,
CASE WHEN a.input = b.input THEN
input_num+1
WHEN a.input <> b.input THEN
INSERT INTO diff_values(file_type,a_input,b_input,report_date)
SELECT file_type,a.input,b.input FROM test1 a, tset2 b WHERE
a.file_type=b.file_type
WHEN a.output = b.output THEN
out_num+1
END CASE
FROM
test1 a, tset2 b
WHERE a.file_type=b.file_type
AND a.report_date=b.report_date;

You cannot embed a DML statement (e.g. INSERT) within a SQL query.
You cannot embed a CASE statement (which is PL/SQL) within a SQL query. You can embed a CASE expression within a SQL query, however, but the expression can only evaluate a result, it cannot include PL/SQL (see #1 above)*.
The outcome you seem to want to achieve is to query some data from two tables (test1 and tset2), evaluate an expression, and insert the result back into the same tables as new records. Since your final outcome is an INSERT, you would start with that and then create a query that gathers the data needed for it, e.g.:
INSERT INTO diff_values(file_type,a_input,b_input,report_date)
SELECT a.file_type,
a.input,
b.input,
a.report_date
FROM test1 a, tset2 b
WHERE a.file_type=b.file_type
AND a.report_date=b.report_date
AND a.input <> b.input;
Note that I've removed the COALESCE because the WHERE clause guarantees both a.file_type and b.file_type are identical anyway, so you can just refer to one of those columns.
Now, your original statement included the following lines as well:
WHEN a.input = b.input THEN
input_num+1
...
WHEN a.output = b.output THEN
out_num+1
I don't know what these are supposed to do, but I suppose you could write additional queries to detect these conditions and output the results.
technically, in Oracle 12.1 you can include procedural code in a WITH clause within SQL https://oracle-base.com/articles/12c/with-clause-enhancements-12cr1

Related

How i can to insert after select statement in SQL?

I using django framework and Postgresql develop my project. But I have a problem when many user requests at the same time. It will double inserted data when server is slow. For this reason, I will try to prevent in SQL. I want to know how to SELECT, then INSERT in one command.
Such as
is_created = select created_at,product from payment where created_at=current_date,product_id = '1'
if is_created == False then
insert into table (...) values (....)
postgreSQL supports conditionals you may find this helpful
https://www.postgresql.org/docs/current/functions-conditional.html
example
CASE expression
WHEN value THEN result
[WHEN ...]
[ELSE result]
END

Using UPDATE statement while using multiple WITH

I have a sql statement that returns records that I need and I am using several WITH clauses. I am trying to update one column within the statement.
WITH <name_a> AS (SELECT...),
<name_b> AS (SELECT...using 'name_a'),
<name_c> AS (SELECT...using 'name_b')
SELECT * from <name_c>
How would I write the statement if I just want to update a column in the final <name_c> output? Ex.
UPDATE name_c SET fav_color = 'blue'
for all the records.
I tried just replacing the select with the update statement but I get 'Missing SELECT keyword'.
I found a similar question but it looks like this question focused on updating the value to what was returned from the select statement. Using "WITH" and "UPDATE" statements in the same SQL query

sql ORA-00900: Invalid SQL statement

please help
IF EXISTS(SELECT * FROM MERC_ADM_VERSION )then UPDATE MERC_ADM_VERSION SET
VER_VALEUR = 20150409 WHERE VER_CLE = 'MEAD' ELSE INSERT INTO MERC_ADM_VERSION
('VER_VALEUR', 'VER_CLE') VALUES (20150409, 'MEAD');
ORA-00900: Invalid SQL statement
Remove the single quotes from the columns in the insert statement.
Instead of
('VER_VALEUR', 'VER_CLE')
It should be
(VER_VALEUR, VER_CLE)
Your question is quite unclear as to what you are trying to do. However, my best interpretation is you are looking for an oracle merge statement. Below is an example based on assumptions I made on the little information you provided. You are most likely looking for a MERGE statement. This allows you to perform a single operation that can either update or insert based on your criteria.
Also, you appear to be using a date, but in number format. I did nothing to address this due to lack of any table definition. You may still have problems with it.
MERGE
INTO merc_adm_version TARGET -- The table you want to update/insert into
USING (SELECT 20150409 as ver_valeur, 'MEAD' as ver_cle FROM dual) SOURCE -- The source of the data
ON (TARGET.ver_cle = SOURCE.ver_cle) -- How to try and match records between source and target
WHEN MATCHED THEN UPDATE SET ver_valeur = 20150409 -- When there is a match, how to update
WHEN NOT MATCHED THEN INSERT (ver_cle, ver_valeur) -- When there is not a match, how to insert
VALUES ('MEAD', 20150409);

Why do I need the 'match' part of a SQL merge, in this scenario?

Consider the following:
merge into T t1
using (select ID,Col1 from T where ID = 123) t2
on 1 = 0
when not matched then insert (Col1) values (t2.Col1);
Cominig from a programming background, to me this translates to:
"Evaluate false (i.e. 1 = 0), and when it is false (i.e. all the time), insert."
Is it not possible to just omit the match condition?
Is it because of my select's where condition that I'm confused here? Should this condition be moved to the on?
NOTE:
Due to restrictions with output, I cannot use insert. I need to output the results of this merge into a temporary table for reasons outside of the scope of what I'm asking.
In the answer you've linked to in the comments, as I've hopefully made clear, we are abusing the MERGE statement.
The query you've shown here could trivially be replaced by:
insert into T(Col1) select Col1 from T where ID = 123
However, if you want to be able to add an OUTPUT clause, and that OUTPUT clause needs to reference both the newly inserted data and data from the source table, you're not allowed to write such a clause on an INSERT statement.
So, we instead use a MERGE statement, but not for its intended purpose. The entire purpose is to force it to perform an INSERT and write our OUTPUT clause.
If we examine the documentation for MERGE, we see that the only clause in which we can specify to perform an INSERT is in the WHEN NOT MATCHED [BY TARGET] clause - in both the WHEN MATCHED and WHEN NOT MATCHED BY SOURCE clauses, our only options are to UPDATE or DELETE.
So, we have to write the MERGE such that matching always fails - and the simplest way to do that is to say that matching should occur when 1 = 01 - which, hopefully, is never.
1Since SQL Server doesn't support boolean literals

Proc Sql case confusion

Within SAS
I have a proc-sql step that I'm using to create macro variables to do some list processing.
I have ran into a confusing step where using a case statement rather than a where statement results in the first row of the resulting data set being a null string ('')
There are no null strings contained in either field in either table.
These are two sample SQL steps with all of the macro business removed for simplicity:
create table test as
select distinct
case
when brand in (select distinct core_brand from new_tv.core_noncore_brands) then brand
end as brand1
from new_tv.new_tv2
;
create table test2 as
select distinct brand
from new_tv.new_tv2
where brand in (select distinct core_brand from new_tv.core_noncore_brands)
;
using the first piece of code the result is a table with multiple rows, the first being an empty string.
The second piece of code works as expected
Any reason for this?
So the difference is that without a WHERE clause you aren't limiting what you are selecting, IE every row is considered. The CASE statement can bucket items by criteria, but you don't lose results just because your buckets don't catch everything, hence the NULL. WHERE limits the items being returned.
Yes, the first has no then clause in the case statement. I'm surprised that it even parses. It wouldn't in many SQL dialects.
Presumably you mean:
create table test as
select distinct
case
when brand in (select distinct core_brand from new_tv.core_noncore_brands)
then brand
end as brand1
from new_tv.new_tv2
;
The reason you are getting the NULL is because the case statement is return NULL for the non-matching brands. You would need to add:
where brand1 is not NULL
to prevent this (using either a subquery or making brand1 a calculated field).
Your first query is not correct, there is no 'then' statement in the 'case' clause.
create table test as
select distinct
case
when brand in (select distinct core_brand from new_tv.core_noncore_brands)
*then value*
end as brand1
from new_tv.new_tv2
;
Probably, you have NULL value because there is no default value for the 'case' clause, so for the value which doesn't meet the condition it returns NULL. There is a difference between 'case' clause and 'NOT IN', the first returns you all the rows, but without values, which do not meet condition, when second query will return only row which meet condition.