Dynamic Name for Database Table - Stored Procedure - sql

I want to create dynamic name for my database tables. I declare variable and use it as my table name.
ERROR: Incorrect syntax near '#sample'. Expecting '.',ID or QUOTED_ID
CREATE PROCEDURE [dbo].[sp_SAMPLE]
#name nvarchar(50)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #sample nvarchar(50);
SET #sample = 'tbl_function_' + #name;
Create Table #sample
(
id int not null,
UserType nvarchar(50) null,
paramater2 nvarchar(50) null
)
END
Is there any way to make my table name dynamic? Thank you.

I'm not sure why you would want to do this. But, you can do it using dynamic SQL:
CREATE PROCEDURE [dbo].[sp_SAMPLE]
#name nvarchar(50)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #sql nvarchar(max);
SET #sql = '
Create Table tbl_function_#name
(
id int not null,
UserType nvarchar(50) null,
paramater2 nvarchar(50) null
)';
SET #sql = REPLACE(#sql, '#name', #name);
EXEC sp_executesql #sql;
END;
Why would you want to create a separate table for each #name, instead of just inserting rows with #name in a column?

CREATE PROCEDURE [dbo].[sp_SAMPLE]
#name nvarchar(50)
AS
BEGIN
SET NOCOUNT ON
DECLARE #sql varchar(4000);
SET #sql = '
Create Table tbl_function_'+#name+'
(
id int not null,
UserType nvarchar(50) null,
paramater2 nvarchar(50) null
)'
EXEC (#sql)
END

Related

SQL Pass Parameters from One stored proc to another

I have two SQL scripts: Script A and B. Script A retrieves information and uses the sp_executesql command to call stored procedure (Script B). I can successfully accomplish this.
However, now i would like to pass a value from Script A to Script B. I am unable to accomplish this. #nID is the parameter I would like to pass. I am using this link as a reference https://msdn.microsoft.com/en-IN/library/ms188001.aspx
My scripts are attached. For simplicity, I just made my parameter value equal to 5. So how do I pass a '5' from one script to another? Thanks for any help.
Script A
BEGIN
SET NOCOUNT ON;
DECLARE #sp nVARCHAR(25)
DECLARE #nID nvarchar(25)
DECLARE #busID nvarchar(25)
DECLARE #ParmDefinition nvarchar(500)
SET #ParmDefinition = N'#nID nvarchar(50) output ';
set #sp = 'WMCOMM';
set #busID = 5
execute sp_executesql #sp, #ParmDefinition, #nID = #busID;
END
Script B
ALTER PROCEDURE [dbo].[WMCM]
AS
BEGIN
SET nocount ON;
declare #numID nvarchar(50)
insert into tester(numid)
values(#numID)
END
Stored procedure B requires an input parameter
ALTER PROCEDURE [dbo].[WMCM]
#nID nvarchar(25) --DECLARE PARAMETER HERE THEN YOU CAN USE IT IN THE SP
AS
BEGIN
SET nocount ON;
declare #numID nvarchar(50)
insert into tester(numid)
values(#numID)
END
Here's a working template of what you are trying to acheive.
--RUN ME FIRST
CREATE procedure dbo.B
#nID AS NVARCHAR(5)
AS
SELECT #nID
GO
--RUN ME SECOND
CREATE procedure dbo.A
AS
DECLARE #nID NVARCHAR(50) = 'abc'
DECLARE #sp NVARCHAR(50) = 'EXECUTE dbo.B #nID'
EXECUTE sp_executesql #sp,N'#nID NVARCHAR(50)',#nID = #nID;
GO
--RUN ME THIRD
EXEC dbo.a
I dumbed-down the stored procedure to only show and return.
But this does what you want:
alter PROCEDURE [dbo].[WMCM]
#nID nvarchar(25) --DECLARE PARAMETER HERE THEN YOU CAN USE IT IN THE SP
, #InAndOutValue nvarchar(50) OUTPUT
AS
BEGIN
SET nocount ON;
Select '[dbo].[WMCM] has access to :' as ProcName , #nID as TheId
Select '[dbo].[WMCM] can use same variable as input and output. InValue :' as ProcName , #InAndOutValue as TheId
select #InAndOutValue= 'NowImAnOutValue'
END
GO
DECLARE #SQL_String NVARCHAR(max)
DECLARE #Parameter_Definition NVARCHAR(max)
SET #SQL_String = N'
EXEC [dbo].[WMCM] #nID = #nID_input, #InAndOutValue = #InAndOutValue_out OUTPUT
'
SET #Parameter_Definition = N'
#nID_input nvarchar(25),
#InAndOutValue_out nvarchar(50) OUTPUT'
DECLARE #nID nvarchar(25)
DECLARE #InAndOutValue nvarchar(50)
SET #nID = '5'
SET #InAndOutValue = 'InAndOutVariable_JustInValue'
EXECUTE sp_executesql #SQL_String, #Parameter_Definition, #nID_input = #nID, #InAndOutValue_out = #InAndOutValue OUTPUT
SELECT #InAndOutValue as IGotTheInAndOutValue

TSQL - Parameters and dynamic table names

Please see the DDL below:
CREATE TABLE Person (ID int identity, Name varchar(30), primary key(ID))
INSERT INTO Person (Name) VALUES ('Ian')
Please see the TSQL below:
Declare #ID int
Declare #Name varchar(30)
set #Name = 'Ian'
select #ID=ID FROM Person WHERE Name=#Name
Print #ID
This works as I would expect i.e. 1 is printed to the screen. I want to make a change so that the table name is dynamic i.e.
Declare #ID int
Declare #Name varchar(30)
Declare #TableName as varchar(30)
set #TableName= 'Person'
set #Name = 'Ian'
select #ID=ID FROM #TableName WHERE Name=#Name
Print #ID
The above SQL obviously does not work. I realise that I have to use TSQL. I have tried using EXEC and sp_executesql, but I can only get part way there. How do I implement this. The SQL statement must be: select #ID=ID FROM #TableName WHERE Name=#Name.
You will need to use dynamic sql for this. Have a look here...
Declare #ID int
Declare #Name varchar(30)
Declare #TableName sysname
DECLARE #Sql NVARCHAR(MAX);
set #TableName= 'Person'
set #Name = 'Ian'
SET #Sql = N'select #ID = ID FROM ' + QUOTENAME(#TableName)
+ N' WHERE Name = #Name'
EXECUTE sp_executesql #Sql
,N'#ID int OUTPUT, #Name varchar(30)'
,#ID OUTPUT
,#Name
PRINT #ID

Output parameter in stored procedure is null

I can't seem to get the output parameter right, it's empty where I'm exepecting 'TEMPTABLE'?
create table TEMPTABLE
(
Id int identity primary key,
Name nvarchar(50) not null,
);
GO
insert into TEMPTABLE(Name) values('Name 1');
GO
DECLARE #PARMOUTP nvarchar(50)
DECLARE #ParameterDefinition AS NVARCHAR(2000)
DECLARE #DestTable VARCHAR(50)
declare #sql nvarchar(max)
set #sql = 'SELECT OBJECT_NAME(OBJECT_ID) AS TABLENAME
FROM SYS.IDENTITY_COLUMNS
WHERE OBJECT_NAME(OBJECT_ID) = #DestTable'
set #DestTable = 'TEMPTABLE'
set #ParameterDefinition = '#DestTable VARCHAR(50), #PARMOUTP VARCHAR(50) OUTPUT'
EXECUTE sp_executesql #sql,
#ParameterDefinition,
#DestTable,
#PARMOUTP OUTPUT
print #PARMOUTP;
print isnull(#PARMOUTP, 'PARMOUTP is null!');
What am I doing wrong here?
Regards,
Mike
Your query is not suited for sp_executesql with one parameter.
In the query you should assign value to that parameter and execute it.
Something like this:
create table TEMPTABLE
(
Id int identity primary key,
Name nvarchar(50) not null,
);
GO
insert into TEMPTABLE(Name) values('Name 1');
GO
DECLARE #PARMOUTP nvarchar(50)
DECLARE #ParameterDefinition AS NVARCHAR(2000)
DECLARE #DestTable VARCHAR(50)
declare #sql nvarchar(max)
set #sql = 'SELECT #PARMOUTP = OBJECT_NAME(OBJECT_ID) AS TABLENAME
FROM SYS.IDENTITY_COLUMNS
WHERE OBJECT_NAME(OBJECT_ID) = #DestTable'
set #DestTable = 'TEMPTABLE'
set #ParameterDefinition = '#DestTable VARCHAR(50), #PARMOUTP VARCHAR(50) OUTPUT'
EXECUTE sp_executesql #sql,
#ParameterDefinition,
#DestTable,
#PARMOUTP OUTPUT
print #PARMOUTP;
print isnull(#PARMOUTP, 'PARMOUTP is null!');
Remember that you are returning scalar value from your dynamic query.
In your dynamic SQL statement, you're never assigning any value to the output parameter!
You're selecting the table name as a result set - but it never gets stored into the output variable.
Try this:
set #sql = 'SELECT #PARMOUTP = OBJECT_NAME(OBJECT_ID)
FROM SYS.IDENTITY_COLUMNS
WHERE OBJECT_NAME(OBJECT_ID) = #DestTable'

Update a Table by Passing Table Name, ColumnName as a Variable Using Cursor

I want to Update a Table. I am getting Table Name and Column Name as a XML DataSet from the Front End. I have written One Cursor for that. But it throws error. Below is my Cursor
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[PMT_Formstatus_Update_Test]
(
#XMLTableNames VARCHAR(MAX)
)
AS
BEGIN
DECLARE #docHandle INT, #ErrorMessage VARCHAR(200), #doc VARCHAR(200)
SET #doc = '<?xml version="1.0" encoding="iso-8859-1" ?>'
DECLARE #Names TABLE
(
TName VARCHAR(50),
CName VARCHAR(50),
IDField VARCHAR(50),
FunctionID INT,
ID INT,
StatusID INT
)
SET #XMLTableNames = #doc + #XMLTableNames
EXEC sp_xml_preparedocument #docHandle OUTPUT, #XMLTableNames
INSERT INTO #Names
SELECT * FROM
OPENXML(#docHandle,'NewDataSet/NameDetails',2)
WITH
(
TName VARCHAR(50),
CName VARCHAR(50),
IDField VARCHAR(50),
FunctionID INT,
ID INT,
StatusID INT
)
DECLARE #FunctionID INT
DECLARE #StatusID INT
DECLARE #ID INT
DECLARE #TableName VARCHAR(50)
DECLARE #ColumnName VARCHAR(50)
DECLARE #IDField VARCHAR(50)
DECLARE #getTables CURSOR
SET #getTables = CURSOR FOR
SELECT FunctionID, TName, CName, StatusID, IDField, ID FROM #Names
OPEN #getTables
FETCH NEXT
FROM #getTables INTO #FunctionID, #TableName, #ColumnName, #StatusID, #IDField, #ID
WHILE ##FETCH_STATUS = 0
BEGIN
UPDATE #TableName SET #ColumnName = 3 WHERE #IDField = #ID
FETCH NEXT
FROM #getTables INTO #FunctionID, #TableName, #ColumnName, #StatusID, #IDField, #ID
END
CLOSE #getTables
DEALLOCATE #getTables
END
How to write Update Query in this case? Please I need all your suggestions...
You need to concatenate them as string then call EXEC('')
EXEC ('UPDATE TableName SET ColumnName1 = 3 WHERE ColumnName2= Value')
Simple Dynamic SQL Example:
DECLARE #SQL NVARCHAR(max),#TableName VARCHAR(128),#ColumnName1 VARCHAR(128),#ColumnName2 VARCHAR(128),#Value NVARCHAR(MAX),#NewValue NVARCHAR(MAX)
SET #TableName='User'
SET #ColumnName1='Session_Id'
SET #ColumnName2='Session_Id_Old'
SET #Value=''''+CAST(NEWID() as NVARCHAR(50))+''''
SET #NewValue=''''+CAST(NEWID() as NVARCHAR(50))+''''
SET #SQL=
REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
'UPDATE [#TableName] SET [#ColumnName1] = #NewValue WHERE [#ColumnName2]= #Value','#TableName',#TableName),
'#ColumnName1',#ColumnName1),'#Value',#Value),'#NewValue',#NewValue),'#ColumnName2',#ColumnName2)
EXECUTE(#SQL)
You should add apostrophes to both sides of old/new values if data types are strings
You can hopefully see why what you've written doesn't work, since it's an update statement to execute against a table variable, which affects no actual columns in that table:
declare #TableName table (ID int not null)
declare #ColumnName1 int
declare #ColumnName2 int
declare #Value int
UPDATE #TableName SET #ColumnName1 = 3 WHERE #ColumnName2= #Value
One means to try and achieve what you're doing are dynamic SQL. It's ugly (and will be more so if the data types in the columns vary). There's no real "meta-programming" system built into T-SQL.

Pass a TABLE variable to sp_executesql

I'm trying to pass a TABLE variable to the sp_executesql procedure:
DECLARE #params NVARCHAR(MAX)
SET #params = '#workingData TABLE ( col1 VARCHAR(20),
col2 VARCHAR(50) )'
EXEC sp_executesql #sql, #params, #workingData
I get the error:
Msg 156, Level 15, State 1, Line 1
Incorrect syntax near the keyword 'TABLE'.
I tried omitting the column specification after 'TABLE'. I also tried to declare the table as a variable inside the dynamic SQL. But no luck...
Seems to me that TABLE variables aren't allowed to be passed as parameters in this procedure?. BTW: I'm running MSSQL2008 R2.
I'm not interested in using a local temp table like #workingData because I load the working data from another procedure:
INSERT INTO #workingData
EXEC myProc #param1, #param2
Which I cannot do directly into a temp varaible (right?)...
Any help appreciated!
If you are using SQL Server 2008, to pass a table variable to a stored procedure you must first define the table type, e.g.:
CREATE TYPE SalesHistoryTableType AS TABLE
(
[Product] [varchar](10) NULL,
[SaleDate] [datetime] NULL,
[SalePrice] [money] NULL
)
GO
or use an existing table type stored in the database.
Use this query to locate existing table types
SELECT * FROM sys.table_types
To use in an stored procedure, declare an input variable to be the table:
CREATE PROCEDURE usp_myproc
(
#TableVariable SalesHistoryTableType READONLY
)
AS BEGIN
--Do stuff
END
GO
Populate the table variable before passing to the stored procedure:
DECLARE #DataTable AS SalesHistoryTableType
INSERT INTO #DataTable
SELECT * FROM (Some data)
Call the stored procedure:
EXECUTE usp_myproc
#TableVariable = #DataTable
Further discussions here.
OK, this will get me what I want, but surely isn't pretty:
DECLARE #workingData TABLE ( col1 VARCHAR(20),
col2 VARCHAR(20) )
INSERT INTO #workingData
EXEC myProc
/* Unfortunately table variables are outside scope
for the dynamic SQL later run. We copy the
table to a temp table.
The table variable is needed to extract data directly
from the strored procedure call above...
*/
SELECT *
INTO #workingData
FROM #workingData
DECLARE #sql NVARCHAR(MAX)
SET #sql = 'SELECT * FROM #workingData'
EXEC sp_executesql #sql
There must be a better way to pass this temporary resultset into sp_executesql!?
Regards
Alex
While this may not directly answer your question, it should solve your issue overall.
You can indeed capture the results of a Stored Procedure execution into a temporary table:
INSERT INTO #workingData
EXEC myProc
So change your code to look like the following:
CREATE TABLE #workingData ( col1 VARCHAR(20),
col2 VARCHAR(20) )
INSERT INTO #workingData
EXEC myProc
DECLARE #sql NVARCHAR(MAX)
SET #sql = 'SELECT * FROM #workingData'
EXEC sp_executesql #sql
Regards,
Tim
Alter PROCEDURE sp_table_getcount
#tblname nvarchar(50) ,
#totalrow int output
AS
BEGIN
Declare #params nvarchar(1000)
Declare #sql nvarchar(1000)
set #sql = N'Select #cnt= count(*) From #tbl'
set #params = N'#tbl nvarchar(50) , #cnt int OUTPUT'
Exec sp_executesql #sql , #params ,#tbl=#tblname , #cnt = #totalrow OUTPUT
END
GO
Please note that the above code will not work as table as a object is out of the scope.It will give you the error: must declare table variable.In order to work around we can do the following.
Alter PROCEDURE sp_table_getcount
#tblname nvarchar(50) ,
#totalrow int output
AS
BEGIN
Declare #params nvarchar(1000)
Declare #sql nvarchar(1000)
set #sql = N'Select #cnt= count(*) From dbo.' + #tblname
set #params = N'#cnt int OUTPUT'
Exec sp_executesql #sql , #params , #cnt = #totalrow OUTPUT
END
GO
So-called TableType is tricky. #Alex version should work. However, to simplify and faster performance, go check sys.tables for matching table name while not compromise security and performance.
Here it is
create proc [dbo].Test11
#t1 AS nvarchar(250), #t2 nvarchar(250)
AS
BEGIN
SET nocount ON;
DECLARE #query AS nvarchar(MAX)
if exists (select * from sys.tables where name = #t1) and
exists (select * from sys.tables where name = #t2)
begin
SET #query = N'select * FROM '+ #t1 + N' join ' + #t2 + N' ON ...' ;
select 'Safe and fast'
print #query
exec sp_executesql #query
end
else
select 'Bad, no way Jose.'
SET nocount OFF;
END
GO