Insert using IF/ELSE statements - sql

I am sorry if my question is not clear or my query is not sufficient to help. I have a procedure that has multiple if/else statement. My goal is to insert one row if that if statements meets the criteria else go further. Something like this:
create or replace procedure abc.xyz
( i_name varchar2
,number number,
sections varchar2)
...
max_date date;
min_date date;
...
if(sum=0)
insert into abc_table
(id,name,number,sections,description,date,amount,price,source,latest_date)
select user_seq.nextval,name,number,max_date,amount,0
,'xyz',trunc(sysdate))
from abc_table x
where x.name=i_name
and x.number=i_name
and x.section=i_section;
elseif (sum>0)
insert into abc_table
(id,name,number,sections,description,date,amount,price,source,latest_date)
select user_seq.nextval,name,number,max_date,amount,0
,'xyz',trunc(sysdate))
from abc_table x
where x.name=i_name
and x.number=i_name;
and x.section=i_section;
when i run my procedure, to insert the calculated value , the values are correct but so many rows were inserted. How can I prevent from multiple insert and make only one row insert ?

You are doing it wrong.
According to the Oracle documentation, The syntax for the Oracle INSERT statement when inserting a single record using the VALUES keyword is:
INSERT INTO table
(column1, column2, ... column_n )
VALUES
(expression1, expression2, ... expression_n );
But the syntax for the Oracle INSERT statement when inserting multiple records using a SELECT statement is:
INSERT INTO table
(column1, column2, ... column_n )
SELECT expression1, expression2, ... expression_n
FROM source_table
[WHERE conditions];
reference: https://www.techonthenet.com/oracle/insert.php
from the link i shared:
If you don't want to insert duplicate:
INSERT INTO clients
(client_id, client_name, client_type)
SELECT 10345, 'IBM', 'advertising'
FROM dual
WHERE NOT EXISTS (SELECT *
FROM clients
WHERE clients.client_id = 10345);

Related

INSERT in CASE expression from subselect PostgreSQL

I am trying to create a query like this
WITH insert1 as (),
...
subselect1 as (SELECT
(CASE
WHEN %s is NOT NULL THEN
(INSERT INTO Duration (duration)
VALUES (ROW (%s, %s)) RETURNING id as id_duration)
ELSE
(INSERT INTO Distance (length)
VALUES (ROW (%s, %s)) RETURNING id as id_distance)
END)),
...
INSERT INTO FinalTable...
I'm having trouble with the syntax, I know. Do you accomplish this by with Insert into?
My plan is:
By one WITH statement make several insertions with returning values and finally insert to the FinalTable. Having only INSERT and RETURNING values it works great - I have to refer them in FinalTable e.g. (SELECT id_point from insert3).
But this case - I would like to return value from insert, wrapped in CASE (%s means parametrized query, variables passed from python). So in case first %s is NOT NULL, I have to insert to table Duration, else I have to insert to table Distance.
When inserting in FinalTable, I have references to these tables (columns idDistance, idDuration) - so I would like to write smth like (..., (SELECT id_duration from subselect1), (SELECT id_distance from subselect1)...)
What's wrong with my syntax?
It's very unclear to me what you are trying to achieve, but maybe you are looking for something like this:
WITH insert1 as (
...
),
insert_duration (id_duration) as (
insert into duration (duration, ....)
select ....
from (
values (..),(..)
) as t(...)
where $1 IS NOT NULL --<< first branch of your CASE expression
returning id
),
insert_distance (id_distance) as (
insert into distance (length, ...)
select ....
from (
values (..),(..)
) as t(...)
where $1 IS NULL --<< ELSE branch of your CASE expression
returning id
)
INSERT INTO final_table
...

How do I store the resulting table from a SELECT query in a variable?

Suppose I have the following query, which returns a filtered table:
select column1,column2,column3 from table1 where table1.column1 = 'dada'
Further, suppose I want to store the resulting values in a variable so that I can use the result later on.
I have read that I can store a single value like so:
declare:
result varchar(20);
begin:
select column1 into result from table1 where table1.column1 = 'dada';
end;
But what about multiple values? There doesn't seem to be a "TABLE" or "DICTIONARY" datatype.
I think you need to use collections in oracle. Below code can help you.
Sample Code:
CREATE TABLE example
("S_ID" NUMBER(1,0) ,
"S_NAME" VARCHAR2(8 CHAR)
);
Insert into example (S_ID,S_NAME) values (1,'A');
Insert into example (S_ID,S_NAME) values (1,'B');
Insert into example (S_ID,S_NAME) values (1,'C');
Insert into example (S_ID,S_NAME) values (2,'A');
Insert into example (S_ID,S_NAME) values (2,'B');
Insert into example (S_ID,S_NAME) values (2,'C');
Insert into example (S_ID,S_NAME) values (3,'A');
Insert into example (S_ID,S_NAME) values (3,'B');
commit;
DECLARE
TYPE type_name IS TABLE OF example%rowtype;
var_type_name type_name;
BEGIN
SELECT *
BULK COLLECT INTO var_type_name
FROM example;
for r in var_type_name.first..var_type_name.last loop
dbms_output.put_line(var_type_name(r).s_id||','||var_type_name(r).s_name);
end loop;
END;
Help link:
https://blogs.oracle.com/oraclemagazine/working-with-collections
Use a view instead.
From W3Schools:
In SQL, a view is a virtual table based on the result-set of an SQL
statement.
Here's how you create one:
create view view1 as select column1,column2,column3 from table1 where
table1.column1 = 'dada'
create view tempTable as select column1,column2,... from table1 where
table1.column1 = 'dada'
declare:
result varchar(20);
begin:
select column1 into result from table1 where table1.column1 = 'dada'; // only work if you have single column in your result
end;
// For Multiple values use implicit cursor like below
FOR c_2151 in (
select column1 from table1 where table1.column1 = 'dada'
) LOOP
DBMS_OUTPUT.PUT_LINE('Display: '|| c_2151.column1);
END LOOP;

The select list for the INSERT statement contains fewer items than the insert list (but is identical)

I am trying to develop a procedure that has this basic structure:
select a.*
into #temp1
from OPENQUERY(otherDB,'SELECT ... FROM ...')a
INSERT INTO [dbo].[Data]
(....)
select *
from #temp1
DROP TABLE #temp1
The amount of columns in the results from the OPENQUERY is identical to the INSERT columns
How could I be catching this error :
The select list for the INSERT statement contains fewer items than the insert list. The number of SELECT values must match the number of INSERT columns.
What if you try to make more specific the select? Example:
insert into dbo.data (col1,col2) select col1,col2.....

Insert into 2 tables from a single select query using TSQL

I am trying to insert into 3 tables from one single select statement. Here is what I am trying to do:
insert into dbo.temp1 (name, location, city)
select name, location, city from mytable.
I want to be able to insert into 3 tables once I run the select statement like inserting into temp1, temp2 and temp3.
How can I do this? Thanks.
You can do it maximum for 2 tables with using output:
insert into dbo.temp1 (name, location, city)
output inserted.name, inserted.location, inserted.city into temp2
select name, location, city from mytable
You can't do this in one step*
What you can do is to insert the initial query into a #temp table (or a #table variable) as a staging area, and then insert into the tables from there. Wrap the steps in a transaction to retain ACID:
BEGIN TRAN
select name, location, city
into #TEMP
from mytable;
insert into temp1(name, location, city)
select name, location, city
from #TEMP;
-- Same for temp2 and temp3.
COMMIT TRAN
* Excluding hacks such as a view with an Instead-of Trigger.
The staging table is important from a concurrency point of view, as repeating the original query 3 times may result in different results if there are interim concurrent changes to the source table.
You can.
With a trick.
Create a view, then create an 'instead of' trigger for insert on that view where you insert the stuff into your tables. If you now insert into your view, you finally insert data in 3 tables. Here's a demo
-- 1. create 3 test tables
create table t1( id int, f1 varchar(20))
create table t2( id int, f2 varchar(20))
create table t3( id int, f3 varchar(20))
go
-- 2. create the view
create view Tt as
select t1.ID, t1.f1, t2.f2,t3.f3
from t1
join t2 on t1.ID=t2.ID
join t3 on t1.ID=t3.id
go
-- 3. create the trigger
create trigger Tr_Test on Tt INSTEAD OF INSERT
AS
BEGIN
SET NOCOUNT ON;
insert into t1 select id,f1 from inserted
insert into t2 select id,f2 from inserted
insert into t3 select id,f3 from inserted
END
GO
-- 4. now do your insert with a single select
insert into tt
select 1,'A','B','C'
-- 5. and watch the 3 tables
select * from t1
select * from t2
select * from t3
voilá, one insert, 3 tables got modified. Wwe don't count the hidden trigger, do we ;-)
There is no way to insert into X tables with one query (Ok it its with insert and output to table).
So you have to write 3 queries.
Or you can generate SQL statments with dynamic queries.
I don't believe you can insert into multiple tables in one statement. You can definitely do it in one transaction, however.
BEGIN TRANSACTION
INSERT INTO dbo.temp1 (name, location, city)
SELECT name, location, city
FROM myTable
INSERT INTO dbo.temp2 (name, location, city)
SELECT name, location, city
FROM myTable2
COMMIT TRANSACTION
You can insert into multiple tables with one select statement using a TRIGGER.
CREATE TRIGGER TEMP2_TEMP3_INSERT ON TEMP1
AFTER INSERT AS
BEGIN
/* create your insert statements for TEMP2 and TEMP3 here
referencing the data from the first insert */
END;
GO
MySQL doesn't support multi-table insertion in a single INSERT statement. Oracle is the only one I'm aware of that does, oddly...
However, you CAN use a transaction and have both of them be contained within one transaction.
MySQL:
START TRANSACTION;
INSERT INTO table1 VALUES ('1','2','3');
INSERT INTO table2 VALUES ('1','2','3');
COMMIT;
SQL Server:
BEGIN TRAN;
INSERT INTO table1 VALUES ('1','2','3');
INSERT INTO table2 VALUES ('1','2','3');
COMMIT;
SQL Server with error catching/rollback:
BEGIN TRANSACTION [Tran1]
BEGIN TRY
INSERT INTO table1 VALUES ('1','2','3')
INSERT INTO table2 VALUES ('1','2','3')
COMMIT TRANSACTION [Tran1]
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION [Tran1]
END CATCH
GO

Stored Procedure Insert (Select and Values)

I'm looking to have a stored procedure that will:
run through Table A and retrieve all IDs.
insert into Table B all IDs (loop) but also static values which aren't found in Table A.
How do I approach this?
CREATE OR REPLACE PROCEDURE TEST AS
BEGIN
select ID from TABLE A;
INSERT INTO TABLE B
(
created_date,
created_by,
ID
)
VALUES ('sysdate', '1', 'RESULTS FROM SELECT QUERY');
END TEST;
Not sure how to merge static data ('sysdate' and '1') with results from a query.
No need for 2 separate queries. This should work with INSERT INTO SELECT:
INSERT INTO TABLEB
(
created_date,
created_by,
ID
)
SELECT 'sysdate', '1', id
FROM TABLEA