How can I parameterize the tablename in a CREATE TABLE expression? - sql-server

I was wondering if syntax exist to express something like the following:
DECLARE #MyTableNameVARCHAR(50)
SET #MyTableName= 'AccountSummary'
CREATE TABLE dbo.#MyTableName
(
Id int NOT NULL IDENTITY(1,1),
AccountId int NOT NULL
Amount real
)
Obviously, the above is not working. I made my scripts working with EXEC, but it seems rather convoluted. Can I use CREATE TABLE with a parameter for the tablename?

DECLARE #MyTableName NVARCHAR(50);
SET #MyTableName = 'AccountSummary';
DECLARE #Sql NVARCHAR(MAX);
SET #Sql = N'CREATE TABLE '+ QUOTENAME(#MyTableName) + N'
(
Id int NOT NULL IDENTITY(1,1),
AccountId int NOT NULL,
Amount REAL
)'
EXECUTE sp_executesql #Sql
OR
DECLARE #MyTableName NVARCHAR(50);
SET #MyTableName = 'AccountSummary';
DECLARE #Sql NVARCHAR(MAX);
SET #Sql = N'CREATE TABLE [#MyTableName]
(
Id int NOT NULL IDENTITY(1,1),
AccountId int NOT NULL,
Amount real
)'
EXECUTE sp_executesql #Sql
,N'#MyTableName NVARCHAR(50)'
,#MyTableName

"Can I use CREATE TABLE with a parameter for the tablename?"
No. You have to use dynamic SQL as you indicate you already have working.
This sort of thing is convoluted by nature.
Depending on what you are actually doing you might feel better about having a app layer constrcut the DDL, rather than doing it all in TSQL.

Related

How can write function inside execute key in sql

Create Function fnRMatrixColorGet1(
#RMID varchar(20)
)
returns varchar(100)
as
begin
EXEC (N'SELECT ' + 'C'+#RMID + ' FROM vwemployeeget where empid='+#RMID)
return
end
As Gordon wrote in the comments, user defined functions in SQL Server can't execute dynamic SQL.
From Create User-defined Functions:
User-defined functions cannot make use of dynamic SQL or temp tables. Table variables are allowed.
However, you can create a stored procedure to do that:
CREATE PROCEDURE stpRMatrixColorGet1
(
#RMID varchar(20)
#MatrixColor varchar(100) OUTPUT
)
AS
DECLARE #Sql nvarchar(4000),
#Column sysname = N'C' + #RMID;
-- White list column name since it can't be parameterized
IF EXISTS
(
SELECT 1
FROM Information_Schema.Columns
WHERE Table_Name = 'vwemployeeget'
AND Column_Name = #Column
)
BEGIN
SET #SQL = N'SELECT #MatrixColor = QUOTENAME('+ #Column +') FROM vwemployeeget where empid = #RMID'
-- Safely execute dynamic SQL using sp_ExecuteSql
EXEC sp_ExecuteSql
#Sql,
N'#RMID varchar(20), #MatrixColor varchar(100) OUTPUT',
#RMID,
#MatrixColor OUTPUT
END

How to retrieve data from Database when I have option of 4 parameters using Stored Procedure?

I have a Database of 10 Columns,
let it be like A,B,C,D,E,F,G,H,I,J
Now if i want to extract data with a mix of 4 options
i.e say B,C,H,J (B is my primary key)
and none of them are mandatory to give data in the option.
say
Case 1 : B,C,H is given as parameters and J is given null
for all such cases I have to make a nested if Else statement ?
Because it will go for 4! (factorial)= 24 cases
Is there any easy option for this???
Yes. One option (but with caveats):
WHERE
(#paramA IS NULL OR Some Condition involving #paramA) AND
(#paramB IS NULL OR Some Condition involving #paramB) AND
....
(#paramH IS NULL OR Some Condition involving #paramH)
The caveat being this might make your stored procedure sensitive to parameter sniffing and cached query plans that are not appropriate for particular sets of parameters.
Another option is to construct dynamic TSQL.
As pointed out by # Damien_The_Unbeliever: Erland Sommarskog's Dynamic Search Conditions in SQL is a great place to start.
Here is an example on how to do this using dynamic SQL but I’d also strongly recommend you read the article Mitch and Demien shared.
CREATE PROCEDURE dbo.SearchProc
(
#param1 datetime,
#param2 int,
#param3 nvarchar
)
AS
BEGIN
DECLARE #sql nvarchar(4000)
DECLARE #parameters nvarchar(300)
SET #sql = 'SELECT * FROM TableName WHERE (1=1) '
if #param1 is not null
SET #sql = #sql + ' AND TableName.Column1 = #param1'
if #param2 is not null
SET #sql = #sql + ' AND TableName.Column2 = #param2'
if #param3 is not null
SET #sql = #sql + ' AND TableName.Column3 = #param3'
SET #parameters = '#param1 datetime, #param2 int, #param3 nvarchar'
EXEC sp_executesql #sql, #parameters, #param1, #param2, #param3
END

Can I specify a database name dynamically in a trigger?

I need to get data from a table in a database who's database name will be determined as a variable during a trigger. I then, knowing this variable need to get a seqno from a table in the determined database for a item which was also determined as a variable during a trigger.
I am trying this route as I assume I need to build the SQL statement before I set it to a variable.
This is not working and I need to know the best way on how I can do this:
DECLARE #SU_SEQNO INTEGER, #SU_NAME VARCHAR(50), #SU_OWNER VARCHAR(15), #SUD_SEQNO INTEGER, #SQL NVARCHAR(500)
SET #SU_OWNER = 'XXX'
SET #SU_NAME = '1ABC234'
SET #SQL ='SELECT #SUD_SEQNO=SEQNO FROM ' + (#SU_OWNER) + '.SU_MAIN
WHERE UNITNAME= ' + #SU_NAME
SET #SUD_SEQNO = (EXECUTE (#SQL))
Thanks alot for any help with this
From: Get result from dynamic SQL in stored procedure
SET #SQL = N'SELECT DISTINCT #FiscalYear = FiscalYear FROM ' + #DataSource;
EXEC sp_executesql #SQL, N'#FiscalYear INT OUTPUT', #FiscalYear OUTPUT;
PRINT #FiscalYear;
I'd re-engineer to use the sp_executesql method as shown above. That should do the trick.
I have amended the code, and it works
declare #su_owner varchar(15) = 'DBTEST'
declare #SU_SEQNO INTEGER=1, #SUD_SEQNO INTEGER=0, #SQL NVARCHAR(500)
DECLARE #ParmDefinition NVARCHAR(500), #SU_NAME_INPUT VARCHAR(50)='SU123'
SET #SU_NAME_INPUT = (SELECT UNITNAME FROM SU_MAIN WHERE SEQNO=#SU_SEQNO)
SET #SU_NAME = (SELECT UNITNAME FROM SU_MAIN WHERE SEQNO=#SU_SEQNO)
SET #SQL = N'SELECT #sud_seqnoOUT=MAX(SEQNO) FROM ' + quotename(#su_owner) + '.[dbo].[SU_MAIN] WHERE UNITNAME]=#SU_NAME_INPUT' ;
SET #ParmDefinition = N'#SU_NAME_INPUT VARCHAR(50),#sud_seqnoOUT INT OUTPUT'
EXEC sp_executesql #SQL,#ParmDefinition,#SU_NAME_INPUT = #SU_NAME,
#sud_seqnoOUT = #SUD_SEQNO OUTPUT

passing a TSQL function database name

Is there any way to pass a tsql function a database name so it can perform selects on that database
ALTER function [dbo].[getemailjcp]
(
#DB_Name varchar(100)
)
Returns varchar(4000)
AS
BEGIN
DECLARE #out varchar (4000);
DECLARE #in varchar (1000);
Set #out =
(select substring
((select ';' + e.email from
(SELECT DISTINCT ISNULL(U.nvarchar4, 'NA') as email
FROM [#DB_Name].dbo.Lists ...
In order to create dynamic SQL statement you should store procedure. For example:
DECLARE #DynamicSQLStatement NVARCHAR(MAX)
DECLARE #ParmDefinition NVARCHAR(500)
DECLARE #FirstID BIGINT
SET #ParmDefinition = N'#FirstID BIGINT OUTPUT'
SET #DynamicSQLStatement=N' SELECT #FirstID=MAX(ID) FROM ['+#DatabaseName+'].[dbo].[SourceTable]'
EXECUTE sp_executesql #DynamicSQLStatement,#ParmDefinition,#FirstID=#FirstID OUTPUT
SELECT #FirstID
In this example:
#DatabaseName is the passed as parameter to your procedure.
#FirstID is output parameter - this value might be return from your procedure.
Here you can find more information about "sp_executesql":
http://msdn.microsoft.com/en-us/library/ms188001.aspx
a better solution might be to replace "#DatabaseName" (a char variable)with:
"DB_NAME(<#DBId>)".
You can then continue to pass in the db names, but 1st converting them to IDs in the fcn. Also kinda resolves the contradiction of building a SQL stmt w/ a char variable in it, if using "sp_executesql" to help guard against SQL injection ("DB_NAME()" isn't a variable/can't be substituted).
So you'd have this:
DECLARE #DynamicSQLStatement NVARCHAR(MAX)
DECLARE #ParmDefinition NVARCHAR(500)
DECLARE #FirstID BIGINT
DECLARE #DBId INT
SET #DBId = DB_ID(#Db_Name) --raise the proper security/robustness** concern if this doesn't resolve.
SET #ParmDefinition = N'#FirstID BIGINT OUTPUT'
SET #DynamicSQLStatement=N' SELECT #FirstID=MAX(ID) FROM ['+DB_NAME(#DBId)+'].[dbo].[SourceTable]'

TSQL dynamic adding of columns in stored procedure

Hi I am writing a large stored procedure, which creates a dynamic report table, of n columns in size, the first 6 are constant the remainder depend on a few arguments passed to the procedure to create the table with the required columns.
The problem that I am having is with the following TSQL
DECLARE #columnname VARCHAR(50)
SET #columnname = 'on_' + #description
IF NOT EXISTS(SELECT * FROM syscolumns WHERE id = OBJECT_ID('reports')
AND NAME = #columnname)
BEGIN
ALTER TABLE reports ADD #columnname VARCHAR(50) NULL
END
I am getting syntax errors with this at the #columnname in the ALTER TABLE statement of the above code.
Also as I am new to this, I am not sure if this is the best way to do this, or if there are better ways in TSQL to generate the required dynamic table.
Try this:
declare #sql nvarchar(100)
set #sql = 'ALTER TABLE reports ADD '+ #columnname+' VARCHAR(50) NULL'
exec sp_executesql #sql
Try
DECLARE #columnname VARCHAR(50)
SET #columnname = '[on_' + #description +']'
IF NOT EXISTS(SELECT * FROM syscolumns WHERE id = OBJECT_ID('reports')
AND NAME = #columnname)
BEGIN
ALTER TABLE reports ADD #columnname VARCHAR(50) NULL
END
Cannot get around having to do it dynamically I believe so change your BEGIN block to something like this:
DECLARE #sql VARCHAR(8000)
BEGIN
SET #sql = 'ALTER TABLE Table_1 ADD '+#columnname+' VARCHAR(50) NULL'
EXEC(#sql)
END

Resources