How a function/procedure can be called inside a insert statement - sql

How a function/procedure can be called inside a insert statement without command parameters. e.g.
Insert into myTable (....) values (1,2,mySP_or_mySDF, 3,4)

You can also use INSERT INTO... SELECT
INSERT INTO myTable (col1, col2, col3....)
SELECT 1, 2, mySP_or_mySDF(), 3, 4
If you want to INSERT data from a stored procedure, then you will need to create a temp table and insert the result into the temp table first, then you can use the result to insert into the final table.

try
Insert into myTable (....) values (1,2,dbo.mySP_or_mySDF(), 3,4)

You cannot call a stored procedure within a SELECT/UPDATE/INSERT statement, with the exception of the statement SQL:
insert into <whatever>
exec <some sql statement here>;
(and related constructs).
Stored procedures do not really return values. Well, they do return an integer. So, you could do:
declare #retval int;
exec #retval = mysp;
insert into myTable(col1, col2, col3, col4)
select 1, 2, #retval, 3, 4
You could have the stored procedure "return" all 4 values, by including the following statement in the sp body:
select 1, 2, <whatever>, 3, 4
and then doing
insert into myTable(col1, col2, col3, col4)
exec mysp;

Related

Query to pull only columns which are relevant or have data for specific where condition

I am trying to write a SQL query (preferably not a stored procedure) to pull specific columns that have data relevant to where condition.
As mentioned in the picture, if I have a where condition on Report column = 'ABC', then the query should return only columns COL1 & COL4, as they only have data for report ABC. Similarly if its Report='PQR' then columns COL2 & COL6.
In a real-life scenario, I have around 90 columns. Preferable need a sub-query or simple SQL statement and not stored procedure as I have to call it from VB app.
Here is a test table
create table report_test (
report varchar(100),
col1 int,
col2 varchar(100),
col3 int,
col4 varchar(100),
col5 varchar(100),
col6 varchar(100)
);
insert into report_test (report, col1, col4) values ('abc', 1, '1');
insert into report_test (report, col2, col6) values ('pqr', '1', '1');
insert into report_test (report, col3) values ('xyz', 1);
insert into report_test (report, col1, col4) values ('abc', 1, '1');
insert into report_test (report, col2, col6) values ('pqr', '1', '1');
insert into report_test (report, col3) values ('xyz', 1);
Thanks in advance.
Here's a stored proc that can get you what you want.
Table example
create table report_test (
report varchar(100),
col1 varchar(100),
col2 varchar(100),
col3 varchar(100),
col4 varchar(100),
col5 varchar(100),
col6 varchar(100)
);
insert into report_test (report, col1, col4) values ('abc', '1', '1');
insert into report_test (report, col2, col6) values ('pqr', '1', '1');
insert into report_test (report, col3) values ('xyz', '1');
Stored procedure
Comments are inline. The basic idea is this:
ask the metadata table information_schema all the columns for the report table
loop through each column
ask the report table whether that column for a given report is not null
if not null, add it as a column to select from
execute the final query with report and selected columns (that were not null)
Now, the procedure.
create procedure getReportInfo
#report varchar(100)
as
begin
-- holds name of the column as each column is checked
declare #col nvarchar(100);
-- holds 1 or 0 - 1 means column was not null for that report
declare #cnt int;
-- this is the SQL that asks DB whether a given column is not null in the database
declare #colSQL nvarchar(max);
-- holds parameter definition for dynamic queries
declare #parameter_definition nvarchar(1000);
-- this is the final SQL that will be executed
declare #s nvarchar(1000);
set #s = 'select report';
declare c cursor read_only for
select column_name from INFORMATION_SCHEMA.columns
where table_name = 'report_test' and column_name <> 'report'
order by ORDINAL_POSITION;
open c;
fetch next from c into #col;
while ##FETCH_STATUS = 0
begin
-- ask DB whether column was not null in the table for a given report
set #cnt = 0;
set #colSQL = concat(
'select #cnt_out = count(*) from report_test where report = #rep_temp and ',
#col, ' is not null'
);
set #parameter_definition = N'#rep_temp nvarchar(100), #cnt_out int OUTPUT';
execute sp_executesql #colSQL,
#parameter_definition,
#rep_temp = #report,
#cnt_out = #cnt output;
-- if column was not null, add it as a selectable field in the final query
if #cnt > 0
begin
set #s = concat(#s, ', ', #col);
end;
fetch next from c into #col;
end;
close c;
deallocate c;
-- execute final query
set #s = concat(#s, ' from report_test where report = #rep_temp');
set #parameter_definition = N'#rep_temp nvarchar(100)';
execute sp_executesql #s,
#parameter_definition,
#rep_temp = #report;
end
go
Execute the procedure
execute getReportInfo 'pqr'
report col2 col6
pqr 1 1
execute getReportInfo 'abc'
report col1 col4
abc 1 1
execute getReportInfo 'xyz'
report col3
xyz 1
This is just an idea. Depending on what you have in your report table, you will have to tweak it. There're a few concepts in this example:
how to create a stored proc
how to send parameters to it
how to use cursors
how to use dynamic queries
how to send parameters to dynamic queries
how to retrieve output from a dynamic query
how to execute a stored procedure
Calling a stored proc from VB
See these articles:
VB6: https://www.codeproject.com/Articles/15222/How-to-Use-Stored-Procedures-in-VB6
VB.NET: SQL Server stored procedure and execute in VB.NET
You can write a query with separate result set for each filter condition and apply UNION ALL for them as given below:
SELECT Col1 AS Colum1, col4 AS Column2
FROM TableName
WHERE Report = 'ABC'
UNION ALL
SELECT Col2 AS Colum1, col6 AS Column2
FROM TableName
WHERE Report = 'PQR'
.
.
.

Insert using IF/ELSE statements

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);

Oracle) Insert multiple rows with one fixed value

I'd like to insert these values in the following fashion:
insert into table (name, action-id) values ('user', select action from actions where name='user2');
The result being:
Inserts along the line of, ('user', 1) ('user', 2) ('user', 3)
I'm noticing this isn't correct sql.
How would I go about accomplishing this?
note)
select action from actions where name='user2'
would return: (1, 2, 3)
You can do it with a loop:
BEGIN
FOR x IN (select action from actions where name='user2') LOOP
insert into table (name, action-id) values ('user', x.action)
END LOOP;
END;
or you could use the INSERT/SELECT syntax:
INSERT INTO table (name, action-id)
SELECT 'user', action
FROM actions WHERE name='user2';
Add the fixed value as a column in your query, and use insert-select instead of insert-values:
insert into table (name, action-id)
select 'user', action from actions where name='user2';
Or can be done by procedure
Create that procedure and run it
create or replace procedure set_action
as
cursor c1 is
select * from user;
person c1%rowtype;
username varchar(8);
begin
username:='user';
for person in c1 loop
insert into table(name,action-id)
values (username,person.action);
end loop;
end;
It can be run by execute set_action;
Example:
create table testing(col1 varchar2(10), col2 varchar2(10));
create table testing2(col1 varchar2(10), col2 varchar2(10));
create table testing3(col1 varchar2(10), col2 int);
insert into testing2 (col1, col2) values ('test2_col1', 'test2_col2');
insert into testing3(col1, col2) values ('steve', 1);
insert into testing3(col1, col2) values ('brad', 2);
insert into testing3(col1, col2) values ('chad', 3);
insert into testing3(col1, col2) values ('nick', 1);
insert into testing(col1, col2)
(select col1 ,(select col2 from testing2) from testing3); -- inserts 4 rows
And finally:
select * from testing;
steve test2_col2
brad test2_col2
chad test2_col2
nick test2_col2

Insert with select max fail in sql for Oracle

When use a bunch of INSERT statements as below it takes forever :
INSERT INTO my_table ( col1, col2, id_col) VALUES ('val1', 'val1', (select max(my_table_ID) from my_table)+1);
If I run one by one and commit then it works fine. What is the reason?
I know sequence should be used in production. But I am writing this to insert few rows in toad.
may be
INSERT INTO my_table ( col1, col2, id_col)
VALUES ('val1', 'val1', (select max(my_table_ID)+1 from my_table));
or in pl/sql block
declare
v_max number(10);
begin
select max(my_table_id) + 1 into v_max
from my_table;
insert into my_table ( col1, col2, id_col)
values ('val1', 'val1', v_max);
end;
/
but, i don't know you task...
may be used sequence + trigger before insert?

Identity Insert Problem

I am trying to run this script:
SET IDENTITY_INSERT dbo.Message ON
INSERT INTO dbo.Message
SELECT (Values I want to insert)
and when I do I still get the error
*An explicit value for the identity column in table 'dbo.Message' can only be specified when a column list is used and IDENTITY_INSERT is ON.*
What am I doing wrong?
The key to your error is "when a column list is used". You want:
SET IDENTITY_INSERT dbo.Message ON
INSERT INTO dbo.Message (column1, column2, ...) -- Added column list here
SELECT (Values I want to insert)
You need to do just as the error message says. Format your code like:
INSERT INTO dbo.Message
(col1, col2, col3, col4)
SELECT Col1, col2, col3, col4
FROM OtherTable
You need the list of fields after the INSERT line, and you need to specify the field names in your SELECT - SELECT * won't work.
You have to mention all the columns Name in both Insert Statement and in select clause.
Some thing like this.
Insert Into tbl
(
[col1],
[col2]
)
SELECT
[col1],
[col2]