How to set data to a variable from temporary table? - sql-server-2008

I have declared a temporary table
DECLARE #Table Table
(
ID INT IDENTITY(1,1),
TableColumn VARCHAR(MAX)
)
DECLARE #Temp VARCHAR(MAX)
SET #Temp='SELECT * FROM '+'#Table'+''
SELECT #Temp
EXEC (#Temp)
I want to set all data of #Table to a variable #Temp. The above I tried practice is correct? Presently it shows some error.
Msg 1087, Level 15, State 2, Line 1
Must declare the table variable "#Table".
I tried in the above methode then it shows error like
Msg 156, Level 15, State 1, Line 1
Incorrect syntax near the keyword 'AS'.
Msg 1087, Level 15, State 2, Line 9
Must declare the table variable "#Table". Msg 139, Level 15, State 1,
Line 0
Cannot assign a default value to a local variable.
Msg 137, Level 15, State 2, Line 17
Must declare the scalar variable "#Temp".

This is to show the difference between a table variable and a temp table. You can't do what you are trying to do. Also, #temp is just a variable to contain the SQL you want to execute. If you want the results in another variable, another will have to be declared.
DECLARE #Table TABLE (
ID INT IDENTITY(1, 1)
,TableColumn VARCHAR(MAX)
)
INSERT INTO #Table (TableColumn)
VALUES ('testing 1,2,3')
SELECT *
FROM #table --with table variables, you can only select in the scope
DECLARE #Temp VARCHAR(MAX)
SET #Temp = 'SELECT * FROM #Table'
BEGIN TRY
--SELECT #Temp
EXEC (#Temp) --fails, because #table is not in scope
END TRY
BEGIN CATCH
SELECT 'Table variable dynamic execution failed'
END CATCH
GO
CREATE TABLE #table (
ID INT IDENTITY(1, 1)
,TableColumn VARCHAR(MAX)
)
INSERT INTO #Table (TableColumn)
VALUES ('testing 1,2,3')
DECLARE #Temp VARCHAR(MAX)
SET #Temp = 'SELECT * FROM #Table' --you can select out of a temp table with dynamic sql, because it will remain in scope for called procedures
--SELECT #Temp
EXEC (#Temp)
DROP TABLE #table

EXEC() creates new context, variables are not visible there so you need to pass them as argument. But temp table and normal tables are visible. This is why you get
Must declare the table variable "#Table".
If you can change temp variables to temp tables.
SqlFiddleDemo
CREATE TABLE #Table
( ID INT IDENTITY(1,1),
TableColumn VARCHAR(MAX));
INSERT INTO #Table
VALUES ('aaa'), ('bbb');
DECLARE #Temp NVARCHAR(MAX) ='SELECT * FROM <placeholder>';
SET #Temp = REPLACE(#Temp, '<placeholder>', '#Table');
-- SELECT #Temp;
EXEC [dbo].[sp_executesql]
#Temp;
If you want to query temp variables you need to create table type and pass to dynamic sql as argument like:
Demo
CREATE TYPE MyTable AS TABLE
(
ID INT IDENTITY(1,1),
TableColumn VARCHAR(MAX)
);
DECLARE #Table AS MyTable;
INSERT INTO #Table
VALUES ('aaa'), ('bbb');
DECLARE #Temp NVARCHAR(MAX) ='SELECT * FROM '+'#Table'+'';
-- SELECT #Temp;
EXEC [dbo].[sp_executesql]
#Temp
,N'#Table MyTable READONLY'
,#Table;

Related

SELECTing the column names for another SELECT - possible?

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

GROUP CONCAT REPLACE sep strings

I am using the below statement to pull a unique value off a table from a field that is separated with "|". It looks like this: "40|180|408|360|40|1s66|80|59" My problem is that I can't seem to get this statement to allow me to pull a primary key field, id, and assign it to each unique item from the field string so I can actually use it later. Ideally, ID # 27 should be assigned to each of the values on this temp table from "40|180|408|360|40|1s66|80|59". Can anyone help with the below statement to allow me to insert and assign field id to this from table BlogImageBundle?
CREATE TEMPORARY TABLE test (postId INT(11), val CHAR(255));
SET #S1 = CONCAT("INSERT INTO test (val) VALUES ('",REPLACE((SELECT GROUP_CONCAT( DISTINCT `images`)
AS data FROM `BlogImageBundle`), "|", "'),('"),"');");
PREPARE stmt1 FROM #s1;
EXECUTE stmt1;
SELECT DISTINCT(val) FROM test;
This works but ONLY for one record. You will need to add another while loop that keeps track of the rowcount to deal with multiple records : http://sqlfiddle.com/#!6/d62f7/1
CREATE TABLE #Test
(
ID INT,
Initial VARCHAR(MAX)
)
CREATE TABLE #Test2
(
ID INT,
Final VARCHAR(MAX)
)
INSERT INTO #Test VALUES(27,'40|180|408|360|40|1s66|80|59')
DECLARE #String VARCHAR(MAX)
SET #string = (SELECT Initial FROM #Test)
DECLARE #StringInput VARCHAR(MAX)
SET #stringInput = (SELECT Initial FROM #Test)
WHILE LEN(#StringInput) > 0
BEGIN
SET #String = LEFT(#StringInput,ISNULL(NULLIF(CHARINDEX('|', #StringInput) - 1, -1),LEN(#StringInput)))
SET #StringInput = SUBSTRING(#StringInput,ISNULL(NULLIF(CHARINDEX('|', #StringInput), 0),LEN(#StringInput)) + 1, LEN(#StringInput))
INSERT INTO #Test2 (ID, Final)
SELECT ID,#string FROM #Test
END

Loop over SQL stored procedure

I have a stored procedure In which insert query fire on two table.
masters_table,child_table as you see here #Value1,#Value2,#Value3,#Value4 having parameter. I have written insert statement for each block, can I make use loop here to avoid multiple insert write for each block, suppose I have nth value then i have to write nth time block wise insert query, any better way to achieve this task
Create proc sp_insert_master_child
(
#Details_Data custom_tb READONLY,
#Value1 nvarchar(500),
#Value2 nvarchar(500),
#Value3 nvarchar(500),
#Value4 nvarchar(500),
#Value5 nvarchar(500),
#Value6 nvarchar(500),
#Value7 nvarchar(500)
)
as begin
declare #id bigint
------- block 1
if #Value1 is not null
begin
insert into masters_table (col1,col2,col3))
select Substring(#Value1, 1,Charindex(',', #Value1)-1) as col_value_1,
Substring(#Value1, Charindex(',', #Value1)+1, LEN(#Value1)) as col_value_2
select #id = ##IDENTITY
insert into child_table (col1,col2,col3)
SELECT #id,col_val_2,col_val_3 FROM #Details_Data WHERE blockType='blk_1';
end
------ block 2
if #Value2 is not null
begin
insert into masters_table (col1,col2,col3))
select Substring(#Value2, 1,Charindex(',', #Value2)-1) as col_value_1,
Substring(#Value2, Charindex(',', #Value2)+1, LEN(#Value2)) as col_value_2
select #id = ##IDENTITY
insert into child_table (col1,col2,col3)
SELECT #id,col_val_2,col_val_3 FROM #Details_Data WHERE blockType='blk_2';
end
------ block 3
if #Value3 is not null
begin
insert into masters_table (col1,col2,col3))
select Substring(#Value3, 1,Charindex(',', #Value3)-1) as col_value_1,
Substring(#Value3, Charindex(',', #Value2)+1, LEN(#Value3)) as col_value_2
select #id = ##IDENTITY
insert into child_table (col1,col2,col3)
SELECT #id,col_val_2,col_val_3 FROM #Details_Data WHERE blockType='blk_3';
end
------ block 4
.......
------ block 5
.......
You can insert all parameters into a table .Use while loop and read one by one row (parameter) from table .
Ex:
declare #x int
set #x= 1
declare #tmp table ( val int )
while (#x < noofrows)
begin
***********
Use Top #x value to get row(parameter in your case) from table
perform your operation
*************
increment x(set #X=#x+1)
end

Getting summary of results from another stored procedure

I have one complex stored procedure that returns some rows with some calculated values
SELECT CalculatedField1 ,
CalculatedField2 ,
...
FROM ...
WHERE CONDITION
this sproc (lets call it procA) returns variable number of rows, depending on the WHERE condition. This works fine. What I need to do now is to write a stored procedure that will get the summary of these returned rows.
-- procB
SELECT SUM(CalculatedField1),
SELECT SUM(CalculatedField2),
...
FROM (EXEC procA params)
Is this possible?
Edit: creating a temp table did the job, however I have problems with passing output pareters.
CREATE PROCEDURE [dbo].[sprocB] (#prm INT = NULL OUTPUT)
AS
BEGIN
SET NOCOUNT ON;
SET #prm = 1
SELECT Id FROM dbo.AnyTable
END
CREATE PROCEDURE [dbo].[sprocA] (#prm INT = NULL OUTPUT)
AS
BEGIN
SET NOCOUNT ON;
CREATE TABLE #temp (Id INT)
INSERT INTO #temp
EXEC sprocB #prm
SELECT Id FROM #temp
END
To execute:
USE [MyDatabase]
GO
DECLARE #return_value int,
#prm int
EXEC #return_value = [dbo].[sprocA]
#prm = #prm OUTPUT
SELECT #prm as N'#prm'
SELECT 'Return Value' = #return_value
GO
The results from temp table are ok, resultset is retrieved correctly, however #pem value is still NULL.
It is possible but you need an auxiliary table:
CREATE PROCEDURE procB
AS
declare #table table (CalculatedField1 int, CalculatedField12 int)
insert into #table
EXEC sp_a
select SUM(CalculatedField1), SUM(CalculatedField2)
from #table
GO
This might do what you want:
create table #scratch (CalculatedField1 int, CalculatedField2 int,...)
insert into #scratch (exec procA params)
select sum(CalculatedField1), sum(CalculatedField2),... from #scratch
drop table #scratch

Dynamic insert into variable table statement SQL Server

I have a variable table:
DECLARE #A_Table TABLE(ID INT, att1 VARCHAR(100), att2 nvarchar(200))
I want to make dynamic sql, so I insert into this table some data (all inside a loop):
WHILE (#i <= 100) BEGIN
SELECT #other_att = NAME FROM #other_Table where ID = #i;
SET #sql = 'INSERT ' + #A_Table+ '(ID,att1,att2) SELECT '+CAST(#i AS VARCHAR)+' , '''+ #other_att+''', SUM('+ #other_att') FROM '+ #EVEN_OTHER_Table;
EXEC (#sql);
END
sql every time would look like:
INSERT INTO #A_Table SELECT 1 , 'subject', SUM(subject)
INSERT INTO #A_Table SELECT 2 , 'age', SUM(age)
INSERT INTO #A_Table SELECT 3 , 'sex', SUM(sex)....
AND after executing this :
SO I will get:
#A_Table:
id att1 att2
1 subject 4.3
2 age 4.5
3 sex 4.1
but I get an error:
Msg 137, Level 16, State 1, Line 48
Must declare the scalar variable "#A_Table".
SO what is it the syntax to insert dynamically into a variable table?
Ok I have understood it.
You could use the INSERT ... EXEC syntax to insert the data returned by the dynamic SELECT. Of course, you would then need to remove the INSERT part from the dynamic statement.
WHILE (#i <= 100) BEGIN
SELECT #other_att = NAME FROM #other_Table where ID = #i;
SET #sql = 'SELECT '+CAST(#i AS VARCHAR)+' , ''' + #other_att+''', SUM('+ #other_att + ') FROM '+ #EVEN_OTHER_Table;
INSERT INTO #A_Table (ID,att1,att2)
EXEC (#sql);
END
You have a table variable, not a variable that contains the table name.
So you would need the following.
WHILE (#i <= 100) BEGIN
SELECT #other_att = NAME FROM #other_Table where ID = #i;
SET #sql = 'INSERT INTO #A_Table (ID,att1,att2) SELECT '+CAST(#i AS VARCHAR)+' , '''+ #other_att+''', SUM('+ #other_att') FROM #EVEN_OTHER_Table';
EXEC (#sql);
END
You would also need to declare the table variable as a statement inside the #sql variable, and execute your declare table and inserts together, or use a local/global temporary table.
With a local temporary table (stored in the tempdb) you could do something like this.
CREATE TABLE #testtbl (ID INT);
EXEC ('INSERT INTO #testtbl VALUES (1)');
SELECT * FROM #testtbl
DROP TABLE #testtbl
Some good info about temporary tables in BOL
http://msdn.microsoft.com/en-us/library/ms174979.aspx - quite far down the page
And the table type.
http://msdn.microsoft.com/en-us/library/ms175010.aspx
Your EXEC statement occurs in a different context and is therefore unaware of any variables created in your original context.
To create dynamic insert query it is really a task, I also struggle to find it ,finally I have tried in the following way and it's successfully working. Please find the code below.
CREATE PROCEDURE [dbo].[InsertTodaysData] (#tbl varchar(50),#Days int,
#MDate varchar(50), #EValue varchar(50), #Speed varchar(50),
#Totalreturn varchar(50),#Closingv varchar(50), #TotalReturnV varchar(50))
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE #SQLQuery varchar(2000)
-- Insert statements for procedure here
set #SQLQuery = 'INSERT INTO '+#tbl+' (ID,MDate,EValue,Speed,TotalReturnRatio,ClosingValue,
TotalReturnValue) VALUES ('+#Days+','''+#MDate+''', '+#EValue+', '+#Speed+',
'+#Totalreturn+', '+#Closingv+', '+#TotalReturnV+')'
EXECUTE(#SQLQuery)
END
Hope this will help you..