SQL Server ERROR Must declare the scalar variable - sql-server

I have to truncate the table but getting error
Must declare the scalar variable "#Table".
Code:
DECLARE #Table VARCHAR(20) = 'ABC'
AS
BEGIN
EXEC ('TRUNCATE TABLE abcDB.dbo.'+#Table) AT [Server]
END

Declare the varaible After AS keyword.
BEGIN
DECLARE #Table VARCHAR(20) = 'ABC'
EXEC ('TRUNCATE TABLE abcDB.dbo.'+#Table) AT [Server]
END

Check if u have any constraints(Foreign key). If exists drop it
DECLARE #Table VARCHAR(20) = 'ABC'
BEGIN
EXEC ('TRUNCATE TABLE abcDB.dbo.'+#Table)
END

Use sp_executesql:
DECLARE #Table VARCHAR(20) = 'ABC'
SET #sql='TRUNCATE TABLE abcDB.dbo.' + #Table
EXEC sp_executesql #sql

Related

Create temp table from dynamic SQL with parameters

Here is my issue. I need to create a temp table after executing dynamic SQL and passing params as follows
CREATE PROCEDURE SP1
#param1 varchar(50),
#param2 varchar(50)
AS
BEGIN
DECLARE #PDef varchar(300)
DECLARE #sql varchar(300)
DECLARE #localparam1 varchar(300)
DECLARE #localparam2 varchar(300)
SET #localparam1 = ....
SET #localparam2 = ....
SET #PDef = '#param1 varchar(50), #localparam1 varchar(300)'
SET #sql = 'SELECT * FROM TABL1 WHERE COL1 = #param1, COL2 in (#localparam1)'
EXEC sp_Executesql #sql, #PDef,
#param1 = #param1, #localparam1 = #localparam1
The above works. How do I get the results into a temp table?
I tried
CREATE TABLE #T1 (col1 varchar(50), col2 varchar(50) )
INSERT INTO #T1
EXECUTE #sql -- didn't work
INSERT INTO #T1
EXECUTE (#sql, #PDef, #param1 = #param1, #localparam1 = #localparam1) -- didn't work either
EDIT: Had Looked at the following samples while using EXECUTE
Dynamic SQL results into temp table in SQL Stored procedure and hence used EXECUTE
The accepted answer was:
INSERT into #T1 execute ('execute ' + #SQLString )
omit the 'execute' if the sql string is something other than a procedure
Now see the comments to that accepted answer that question that accepted answer :-)
You've removed sp_executesql from your query for some reason. You can't called sys.sp_executesql if you don't tell SQL Server to:
INSERT INTO #T1
EXECUTE sys.sp_executesql #sql;
INSERT INTO #T1
EXECUTE sys.sp_executesql #sql,
#PDef,
#param1 = #param1,
#localparam1 = #localparam1;

How to store the result of exec in a variable

How can I store the result of exec in a variable? The output is JSON.
My SQL query is complex and dynamically generated, so I have to set a variable and execute it.
create PROCEDURE dbo.RetrievePerfCounterData #jsonOutput NVARCHAR(MAX) OUTPUT
AS
BEGIN
declare #sql NVARCHAR(MAX)
SET #sql = ' SELECT TOP (1) getdate() AS ''dateTime'' ,suser_sname()AS ''user'' FOR JSON PATH '
exec (#sql)
END
Here's my attempt at storing the data in a variable:
DECLARE #json AS NVARCHAR(MAX)
EXEC dbo.RetrievePerfCounterData #jsonOutput = #json OUTPUT
DECLARE #myVar VARCHAR(MAX)
DECLARE #SQL NVARCHAR(MAX)
IF OBJECT_ID('tempdb..#t1') IS NOT NULL DROP TABLE #t1
CREATE TABLE #t1 (col1 INT, col2 INT)
INSERT INTO #t1
SELECT 1, 1
UNION
SELECT 1, 2
SET #SQL = 'SET #myVar = (SELECT * FROM #t1 AS T FOR JSON AUTO);'
EXEC sp_executesql #SQL, N'#myVar VARCHAR(MAX) OUT', #myVar OUT
SELECT #myVar
You need to use a subquery:
SET #json = (SELECT TOP (1) getdate() AS [dateTime],suser_sname()AS [user] FOR JSON PATH);

SQL Server declare and execute query for temp table

I have a temp table like
DECLARE #t TABLE (a BIGINT)
I want to do this
SELECT * FROM #t
but I need to do it by EXEC query, and this doesn't work
DECLARE #query AS NVARCHAR(100) = 'SELECT * FROM #t'
EXEC(#query)
how can I create a custom query to select the temp table?
Thanks.
This is because EXEC statement will execute the Statements in new Session. And the Table variables scope is fixed to the batch of statement.
Since you declared the Table Variable out side of the Session , you can't access the table variable in EXEC statement.
So you need to DECLARE ,INSERT, UPDATE, SELECT table variables in the Dynamic Code itself.
DECLARE #query NVARCHAR(MAX)='';
SELECT #query ='
DECLARE #t TABLE
(
a BIGINT
)'
SELECT #query += 'SELECT * FROM #t'
EXEC(#query)
Solution 2:
The another Solution is to create Global Temporary Table which we can create using ##. And Global Temporary tables scope is limited to Database all connections.
CREATE TABLE ##TABLE1
(
a BIGINT
)
DECLARE #query NVARCHAR(MAX)='';
SELECT #query += 'SELECT * FROM ##TABLE1'
EXEC(#query)
But be aware if another user execute the same Query, there might be conflict with the same name creation.
Try hash table as below:
DECLARE #tblTest AS Table
(
Name VARCHAR(50)
)
insert into #tblTest values('Sandip')
insert into #tblTest values('AAA')
IF OBJECT_ID('tempdb..#tblTest') IS NOT NULL
DROP TABLE #tblTest
SELECT * INTO #tblTest FROM #tblTest
DECLARE #query AS NVARCHAR(100) = 'SELECT * FROM #tblTest'
EXEC (#query)
Output:
CREATE TYPE MyTable AS TABLE
(
a BIGINT
);
GO
DECLARE #T AS MyTable;
EXEC sp_executesql
N'SELECT * FROM #T',
N'#T MyTable READONLY',
#T=#T
please try this

How do I pass an existing table to a procedure? How do I use this... table-valued parameters thingys? look at my code below please

I have many tables that need ID scramblers, so:
CREATE PROCEDURE SP_generateUniqueID ( -- pass table here somehow -- )
AS
BEGIN
DECLARE #ID varchar(100) -- NEW ID.
DECLARE #isIDInUse tinyint -- BOOLEAN YES/NO.
SET #isIDInUse=1
WHILE(#isIDInUse=1) -- KEEP GENERATING TILL YOU FIND ONE:
BEGIN
SET #ID= dbo.generateID('aA1a1') -- GENERATES ID. doesn't matter how.
IF (#ID NOT IN (#passedTable)) -- DOES #ID EXIST ALREADY?
/*(SEARCHES THE PASSED TABLE! Which its size will be 1XN)*/
SET #isIDInUse=0 -- NO, YOU CAN USE.
END
RETURN #ID
END
I can't make the passing of the existing table go smoothly...
I want to be able to insert any table that uses IDs.
Any suggestion?
I would advise you REALLY look hard into better solutions for this issue. You will be hitting your table/index with every iteration of the new ID that you generate. What is wrong with an auto-incrementing integer value:
create table IDs (ID int identity(1,1))
(also, SQL Server has bit data types for boolean values. No need for your tinyint)
That aside, the only way I think you can do this your way is with dynamic SQL. Using the script below you should be able to see how you can pass in your schema.table to the stored procedure and within the procedure define your ID to be inserted in to the checking loop:
create table a(ID nvarchar(100)) insert into a values('1'),('2'),('3'),('4'),('5')
create table b(ID nvarchar(100)) insert into b values('6'),('7'),('8'),('9'),('10')
declare #Table nvarchar(100) = 'dbo.a'
declare #ID nvarchar(100) = '6'
declare #IDinUse bit = 0
declare #sql nvarchar(max) = 'if exists(select ID from ' + #Table + ' where ID = #ID) select #IDinUse = 1 else select #IDinUse = 0'
exec sp_executesql #sql, N'#ID nvarchar(100), #IDinUse bit output', #ID = #ID, #IDinUse = #IDinUse output
select #IDinUse as IDinUse
go
declare #Table nvarchar(100) = 'dbo.b'
declare #ID nvarchar(100) = '6'
declare #IDinUse bit = 0
declare #sql nvarchar(max) = 'if exists(select ID from ' + #Table + ' where ID = #ID) select #IDinUse = 1 else select #IDinUse = 0'
exec sp_executesql #sql, N'#ID nvarchar(100), #IDinUse bit output', #ID = #ID, #IDinUse = #IDinUse output
select #IDinUse as IDinUse

How can we use EXEC sp_executesql for two dynamic SQL statements?

tables:
create table TabA
(ID int, Name varchar(20))
insert into TabA
select 1,'ABC' union
select 2,'DEF' union
select 3,'GHD'
create table TabB
(ID int, Name varchar(20))
insert into TabA
select 1,'XYZ' union
select 2,'STF' union
select 3,'LDZ'
create table status
(Result1 int,Result2 int )
Create table query(query1 varchar(1000),query2 varchar(1000))
Insert into query(query1,query2)
select '''select COUNT(*) from TabA''','''select COUNT(* )from TabB'''
select * from query
procedure:
create Procedure [dbo].spStatus
AS
BEGIN
SET NOCOUNT ON;
Declare #sqlString1 nvarchar(1000)
,#sqlString2 nvarchar(1000)
,#col_value1 varchar(256)
,#col_value2 varchar(256)
select #sqlString1 = query1
, #sqlString2 =query2
from Query
EXEC sp_executesql
#query=#sqlString1, --sql string is your full select statement
#params = N'#col_Value1 varchar(256) OUTPUT',
#col_Value1 = #col_Value1 OUTPUT
print(#sqlString1)
-- #sqlString2, --sql string is your full select statement
--#params = N'#col_Value2 varchar(256) OUTPUT',
-- #col_Value2 = #col_Value2 OUTPUT
Insert Into dbo.Status(Result1,Result2 )
Values(#col_Value1,#col_Value2)
End
It works if we use #query=#sqlString1 only but I want both statement #query=#sqlString1,#query=#sqlString2 should execute together.
Please help how can we use both statement to execute?
Thanks in Advance
Did you mean:
SET #sqlString1 = #sqlString1 + ';' + #sqlString2;
EXEC sp_executesql #query = #sqlString1 --...
Concat the two queries together with a + (#query=#sqlString1 + '; ' + #sqlString2)
Then use two variables to capture the two counts into output variables
OR
Insert into query(query1,query2)
EXEC sp_executesql 'SELECT ( select COUNT(*) from TabA ) AS query1, ( select COUNT(*)from TabB ) AS query2'
... but really and truly dynamic SQL isn't needed for that at all.
try this:
--add this
DECLARE #SQL nvarchar(max)
SET #SQL=ISNULL(#sqlString1,'')+';'+ISNULL(#sqlString2,'')
--change this
EXEC sp_executesql #query=#SQL
,#params = N'#col_Value1 varchar(256) OUTPUT'
,#col_Value1 = #col_Value1 OUTPUT

Resources