This is probably trivial to most of you, but I haven't been writing stored procedures for very long (6 months only). I'd like to be able to set the variable #testid based on one of the columns being used for an INSERT query. How can I do this?
DECLARE #testid INT;
INSERT INTO [exporttestresultreport] (
[testid],
[othercolumn]
)
SELECT
[testid], -- <======= how can I set my variable based on this column?
[othercolumn]
FROM
[exporttestresultreport] e
WHERE
[exporttestresultreportid] = #exporttestresultreportid
DECLARE #testid INT;
DECLARE #test TABLE (testid int);
INSERT INTO [exporttestresultreport] (
[testid],
[othercolumn]
)
OUTPUT INSERTED.testID INTO #test
SELECT
[testid], -- <======= how can I set my variable based on this column?
[othercolumn]
FROM
[exporttestresultreport] e
WHERE
[exporttestresultreportid] = #exporttestresultreportid;
SELECT #testid = testid FROM #test;
An INSERT..SELECT.. is inherently multirow so it doesn't make semse to allow assigning a value to a scalar variable: what row should be used for the value?
DECLARE #testid INT;
DECLARE #t TABLE(t INT);
INSERT exporttestresultreport
(
testid, othercolumn
)
OUTPUT INSERTED.testid INTO #t
SELECT testid, othercolumn
FROM
[exporttestresultreport] e
WHERE
[exporttestresultreportid] = #exporttestresultreportid;
SELECT #testid = t FROM #t;
-- not sure what you want to do if there are multiple rows in the insert
Related
I have a table t1 with a 'foo' column, and records containing 'bar' and 'baz' in column 'foo'. I also have a table t2 with columns 'bar', 'baz' and 'quux'. I want to do something like the following:
SELECT (SELECT foo from t1) FROM t2;
that is, get the two column names from t1 and query those columns of t2. If I try to do this with MonetDB, I get an error message:
cardinality violation (2>1)
so,
is there some other way to do this with MonetDB?
is this possible in MySQL? other DBMSes?
Example queries (or non-query directives followed by a query) are welcome.
first you need to select the columns into a variable and then use that variable to get tables
something like the following (it is not the actual implementation)
declare #colname varchar(250)
select #colname=foo from t1
select #colname from t2
this may be help.
This is how you can accomplish it in SQL Server
-- Create #T1 which contains names of columns and #T2 which contains the actual columns
CREATE TABLE #T1(colname nvarchar(max))
INSERT INTO #T1 (colname) VALUES ('b')
INSERT INTO #T1 (colname) VALUES ('c')
CREATE TABLE #T2(a int IDENTITY(1,1), b DATETIME DEFAULT GETDATE(), c NVARCHAR(max) DEFAULT 'blah')
INSERT INTO #T2 DEFAULT VALUES
INSERT INTO #T2 DEFAULT VALUES
INSERT INTO #T2 DEFAULT VALUES
--#dSQL will contain the actual SQL string to be executed
DECLARE #dSQL nvarchar(max) = ' '
SELECT #dsql = CONCAT(#dsql,'[',colname,'],') FROM #T1
SELECT #dsql = CONCAT('SELECT',LEFT(#dsql,LEN(#dsql)-1),' FROM #T2')
--You can see the SQL query being executed
PRINT #dsql
--Actually execute it
exec sp_executesql #dsql
MS Sql dynamic sql example.
create table t1(foo varchar(100))
insert t1(foo)
values('bar,baz');
create table t2(bar int, baz int)
insert t2 (bar, baz)
values
(1,100),
(3,300);
declare #cmd varchar(max);
select #cmd= 'select '+ (select top(1) foo from t1) + ' from t2';
EXEC (#cmd);
Result
bar baz
1 1 100
2 3 300
Or may be foo contains column names in different rows, not exactly clear from your question.
create table t1(foo varchar(100))
insert t1(foo)
values('bar'),('baz');
create table t2(bar int, baz int)
insert t2 (bar, baz)
values
(1,100),
(3,300);
declare #cmd varchar(max);
select #cmd= 'select '+ stuff((select ','+ foo from t1 for xml path('')),1,1,'') + ' from t2';
EXEC (#cmd);
could you please give me an advice how to CALL prcd with SELECT results? Or advice me pls better solution.. I am open minded to all working solution
I have a procedure to control inserting data ...
CREATE PROCEDURE control_insert (
)
And I need to pass data from SELECT results to procedure ...
SELECT t.c1, t.c2
FROM table t1
LEFT JOIN other_table t2
ON t1.id = t2.id
WHERE 1=1
The point is, I need to get some data via SELECT (around 6 tables joined to the base table) and I need to do control for each row before insert.. each row should meet some conditions .. if it doesn't meet them, it should just skip it and process next one ...
The procedure should look like:
CREATE PROCEDURE control_insert (
IN v_c1 INT,
IN v_c2 INT
)
BEGIN
IF v_c1 > 1 THEN
INSERT INTO controlled_table (id, type) VALUES (v_c1, v_c2);
ELSE
/* do nothing */
END IF;
END;
CALL control_insert ( SELECT .... );
Could you help me with that? Is there any possibility to do this via MySQL? I can write a PERL skript, but I want to avoid this type of solution ... I just one to do it only in MySQL way
Thank you
EDIT1: I need to check if ID of the SELECT result and LABEL is already in this table for specific date ... this code above is only an example to demonstrate the situation
SOLUTION
I've found the solution ... so for the other visitors:
calling procedure:
CALL controlInsert();
procedure body:
CREATE PROCEDURE controlInsert()
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE v_id INT;
DECLARE v_id_dupl INT;
DECLARE v_label INT;
DECLARE v_date DATE;
DECLARE v_type VARCHAR(100);
DECLARE v_category VARCHAR(255);
DECLARE v_user VARCHAR(255);
DECLARE v_country VARCHAR(255);
DECLARE c1 CURSOR FOR SELECT id, label, date, type, category, user, country FROM t1 LEFT JOIN ... /* whole select with 6 joins ended by ; */
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
## open cursor
OPEN c1;
## loop through the cursor
read_loop: LOOP
## fetch cursor into variables
FETCH c1 INTO v_id , v_label, v_date, v_type, v_category, v_user, v_country;
## check if there is any record
IF done THEN
LEAVE read_loop;
END IF;
## get count of existing records
SELECT count(*) INTO v_id_dupl
FROM
WHERE 1=1
AND id = v_id
AND label= v_label
AND date = v_date;
## if v_id_dupl = 0 => no rows found (ok to load)
IF (v_id_dupl = 0) THEN
INSERT INTO target_table (id, label, date, type, category, user, country)
VALUES (v_id , v_label, v_date, v_type, v_category, v_user, v_country);
END IF;
END LOOP;
CLOSE c1;
END
If that is all your stored procedure is doing, then you don't actually need it. You can do the whole thing in a single statement:
INSERT INTO controlled_table (id, type)
SELECT t.c1, t.c2
FROM table t1
LEFT JOIN other_table t2 ON t1.id = t2.id
WHERE something = somethingElse
AND t.c1 > 1
Essentially, I've just combined your original query with the INSERT statement in your procedure.
If your procedure is more complex and needs to do multiple operations on each row, then you should look into using a cursor.
In SQL Server, I am passing String as parameter :
#Param1 = Test,Test1,Test2
I am formatting it to:
#Param1 = 'Test','Test1','Test2'
When I am trying to use this in SELECT statement with IN parameter, it is not returning any data
SELECT * FROM TABLE1 where COLUMN1 IN (#Param1)
What is the correct syntax?
As pointed out already in the comments by marc_s, IN requires a list of values not simply one variable.
But you could provide those values in a SELECT from a simple table variable like this:
DECLARE #Param1 TABLE (Value NVARCHAR(255));
INSERT INTO #Param1 (Value)
SELECT 'Test1'
UNION
SELECT 'Test2'
UNION
SELECT 'Test3'
SELECT
*
FROM TABLE1
WHERE
COLUMN1 IN
(SELECT Value FROM #Param1)
I wish there were array vars like that! :-)
But you can convert it to a table using a function, and then use the table with your IN clause as you're attempting.
Here is how that would look:
DECLARE #Param1 nvarchar(max)
SET #Param1 = 'Test,Test1,Test2'
SELECT *
FROM myTable
WHERE myField In (Select ParsedString From dbo.ParseStringList(#Param1))
And here is (at least one way to write) the function:
CREATE Function [dbo].[ParseStringList] (#StringArray nvarchar(max) )
Returns #tbl_string Table (ParsedString nvarchar(max)) As
BEGIN
DECLARE #end Int,
#start Int
SET #stringArray = #StringArray + ','
SET #start=1
SET #end=1
WHILE #end<Len(#StringArray)
BEGIN
SET #end = CharIndex(',', #StringArray, #end)
INSERT INTO #tbl_string
SELECT
Substring(#StringArray, #start, #end-#start)
SET #start=#end+1
SET #end = #end+1
END
RETURN
END
I have a sql stored proc where I use a cursor that contains a set of id's from a select statement and I use these id's going over one by one using the cursor to get values into other variables and use those variables to do sql joins .My problem is when I execute this I get many tables returned whereas I need just one table returned.
SET NOCOUNT ON
declare #BSVal as int
declare #GSVal as int
declare #mID as int
declare #qID as int
DECLARE M_Cursor cursor for
select
ms.MID,ms.QID
from vM As ms join QS as qs
ON ms.QSID=qs.QIDjoin
Mar as mar on mar.MarID=qs.MarID
where (ms.Cid='Web')
open M_Cursor
FETCH NEXT FROM M_Cursor
INTO #mID, #qID
--Get values
WHILE ##FETCH_STATUS = 0
BEGIN
set #BSVal= (select top 1 SCID from vSC where (EnID in
(select EnID from En where EnName='BAIDU')
and QTID=1 and MID=#mIDand QSID=#qID)order by ITime desc);
set #GSVal= (select top 1 SCID from vSC where ( EnID in
(select EnID from En where EnName='GRAPHIC') and QTID=1
and MID=#mIDand QSID=#QSID) order by ITime desc);
select * from
vM m
join vw5TABLE BNDCG on (m.QSid=BNDCG.QID And BNDCG.Position=1)
join vw5TABLE GNDCG on (m.QSid=GNDCG.QID And GNDCG.Position=1)
where
BNDCG.SCid=#BSVal
and GNDCG.SCid=#GSVal
and BNDCG.QSID=# qID
and GNDCG.QSID=# qID
and m.MID=#mID
FETCH NEXT FROM M_Cursor
INTO #MID, #QSID
END
CLOSE M_Cursor;
DEALLOCATE M_Cursor;
That code will run a select for each iteration of the cursor, which makes it look like 'many tables'. It sounds like you need to insert the results of that select into a temp table or table variable inside the cursor, then once the cursor is complete, select once from that temp table. I have not gone over your code in detail but I'm guessing a cursor may not be required for this.
Here's a rough sample using a table variable.
DECLARE #temptable TABLE (col1 INT, Col2 VARCHAR(3), Col3 INT)
insert into #temptable (col1,col2,col3)
select (col1,col2,col3) from
vM m
join vw5TABLE BNDCG on (m.QSid=BNDCG.QID And BNDCG.Position=1)
join vw5TABLE GNDCG on (m.QSid=GNDCG.QID And GNDCG.Position=1)
where
BNDCG.SCid=#BSVal
and GNDCG.SCid=#GSVal
and BNDCG.QSID=# qID
and GNDCG.QSID=# qID
and m.MID=#mID
....
..
DEALLOCATE M_Cursor;
SELECT Col1,Col2,Col3 FROM #temptable
I wish to compare a variable #a containing an entire column of a table with another variable containing a single value. Is it possible?
create procedure pc1(#var int)
as begin
declare #a int
select #a=id from tb1
while(if exists(#var=#a))
begin
select * from tb1 where id=#var
end
return
end
There is no direct way but you can do this thing in following way.
declare #a int
Set #a = 1
if exists(
select #a as ID
Intersect
Select ID
from tbl
)
Print('Hello')