using Dynamic SQL - Custom Universal Multi-Action Stored Procedure (with TVPar) - sql-server

this is the stored procedure i have started to write
the problem is i couldn't figure out how to handle the part of reading values from the TV par :
Must declare the table variable "#TestMultiActionViaRowIndexTVPar".
ALTER Proc [dbo].[MultiActionViaRowIndexSpTVP]
#SelectedSDTOName varchar (50), #SelectedAction varchar(10), #TestMultiActionViaRowIndexTVPar dbo.TestMultiActionViaRowIndexTVType READONLY
as BEGIN
declare #CmdStr varchar(500) = '';
if(#SelectedAction = 'SELECT') Begin --test for one of the "Action" types
SET #CmdStr = 'SELECT * FROM ' + #SelectedSDTOName +
' WHERE RowIndex in (SELECT RowIndex FROM #TestMultiActionViaRowIndexTVPar)'
End
--else - other Action - #CmdStr will be according to action...
--finally execute constructed Cmdstr
Exec(#CmdStr);
END

Use sp_executesql to pass a TVP or any other parameter to parameterized dynamic SQL:
ALTER PROC [dbo].[MultiActionViaRowIndexSpTVP]
#SelectedSDTOName varchar (50)
, #SelectedAction varchar(10)
, #TestMultiActionViaRowIndexTVPar dbo.TestMultiActionViaRowIndexTVType READONLY
AS
DECLARE #CmdStr nvarchar(MAX);
IF #SelectedAction = 'SELECT'
BEGIN
SET #CmdStr = 'SELECT * FROM ' + #SelectedSDTOName +
' WHERE RowIndex in (SELECT RowIndex FROM #TestMultiActionViaRowIndexTVPar);'
END;
EXEC sp_executesql
#CmdStr
,N'#TestMultiActionViaRowIndexTVPar dbo.TestMultiActionViaRowIndexTVType READONLY'
,#TestMultiActionViaRowIndexTVPar = #TestMultiActionViaRowIndexTVPar;
GO

Related

Must declare the scalar variable error for stored procedure in nopcommerce 4.3

I want to search GTIN option in admin product list. So, for that I am providing GTIN value in ProductLoadAllPaged store procedure. Now, when I search GTIN value from product list at that time throw datatable error and from console application get message that System.Data.SqlClient.SqlException (0x80131904): Must declare the scalar variable "#GTIN"..
Here is store procedure added code,
ALTER PROCEDURE [dbo].[ProductLoadAllPaged]
(
#GTIN nvarchar(50) = null--AWAZ
)
AS
BEGIN
...........
--SKU (exact match)
IF #SearchSku = 1
BEGIN
SET #sql = #sql + 'OR p.[Sku] = #OriginalKeywords '
END
--NEW ADDED CODE FOR GTIN SEARCH
IF #GTIN is not null
BEGIN
SET #sql = #sql + 'AND p.Gtin = #GTIN'
END
--localized product name
SET #sql = #sql + '
UNION
SELECT lp.EntityId
FROM LocalizedProperty lp with (NOLOCK)
WHERE
lp.LocaleKeyGroup = N''Product''
AND lp.LanguageId = ' + ISNULL(CAST(#LanguageId AS nvarchar(max)), '0') + '
AND ( (lp.LocaleKey = N''Name'''
..........
END
In the stored procedure change this line of code:
EXEC sp_executesql #sql, N'#Keywords nvarchar(4000), #OriginalKeywords nvarchar(4000)', #Keywords, #OriginalKeywords
To this:
EXEC sp_executesql #sql, N'#Keywords nvarchar(4000), #OriginalKeywords nvarchar(4000), #GTIN nvarchar(50)', #Keywords, #OriginalKeywords, #GTIN
This will add your new parameter when executing the dynamic SQL query.

Call a Stored Procedure or Function from Dynamic SQL - with Nullable Parameter

I am trying to call an sql function accepting a nullable parameter - from a dynamic SQL statement.
Creating the dynamic statement is difficult because when the parameter value is 'NULL' the concatentation causes the whole statement to be empty. I have the following:
SET dynamicQuery =
'select * from [qlik].udf_getStatistic( ''' + #myParameter + ''' )'
The sample above is inside a stored procedure to which #myParameter is passed. It may be null, or a string value. Clearly, when it is a string it needs to be enclosed in quotes, but when it is null it must not be enclosed in quotes. As follows:
select * from [qlik].udf_getStatistic( 'Heights' )
select * from [qlik].udf_getStatistic( NULL )
The question is equally applicable to calling a stored procedure accepting a nullable parameter from dynamic SQL.
The examples are from SQL Server.
Just escape the NULL value with an explicit literal NULL, making sure that the quotes are only included when the value is not NULL.
DECLARE #myParameter VARCHAR(10) = 'ABC'
DECLARE #dynamicQuery VARCHAR(MAX)
SET #dynamicQuery =
'select * from [qlik].udf_getStatistic(' + ISNULL('''' + #myParameter + '''', 'NULL') + ')'
SELECT #dynamicQuery -- select * from [qlik].udf_getStatistic('ABC')
SET #myParameter = NULL
SET #dynamicQuery =
'select * from [qlik].udf_getStatistic(' + ISNULL('''' + #myParameter + '''', 'NULL') + ')'
SELECT #dynamicQuery -- select * from [qlik].udf_getStatistic(NULL)
You might want to escape additional single quotes that might be on your variable, replacing them with double single quotes, so it doesn't break your dynamic build.
The answer is actually different between stored procedures and functions.
From Books On Line or whatever they call it this month (Scroll down a ways):
When a parameter of the function has a default value, the keyword DEFAULT must be specified when the function is called to retrieve the default value. This behavior is different from using parameters with default values in stored procedures in which omitting the parameter also implies the default value. However, the DEFAULT keyword is not required when invoking a scalar function by using the EXECUTE statement.
So for a proc, when you want to pass a NULL parameter, you can just not pass it. For a function, though, you have to tell it to use the DEFAULT value explicitly. Either way, you do not pass it an explicit NULL. Luckily for your dynamic SQL, though, the explicit DEFAULT also works with a stored procedure. In both cases, in order to make sure that the parameters you are passing get assigned correctly, you want to use explicit parameter names in your call.
Let's use this function definition:
CREATE FUNCTION (or procedure) [qlik].udf_getStatistic (
#param1 integer = 0,
#param2 varchar(100) = 'foo'
) AS ...
Both parameters are optional. Since this is a function, this call will throw an insufficient number of parameters error:
select * from [qlik].udf_getStatistic( 'Heights' );
If it were a procedure call, it would throw a cannot convert value 'Heights' to data type integer because it will apply the only parameter value passed to the first parameter it encounters, which is expecting an integer. In both cases, you get what you want this way:
select * from [qlik].udf_getStatistic( #param1 = DEFAULT, #param2 = 'Heights' );
Which brings us to your dynamic SQL. Add your parameter name(s) to the static text, then use COALESCE (or CASE if you like) to decide whether to pass an explicit value, or the DEFAULT call.
DECLARE #myParameter1 VARCHAR(100) = 'foo',
#myParameter2 INTEGER,
#SQL NVARCHAR(MAX);
SET #SQL =
'select
*
from [qlik].udf_getStatistic(
#param1 = ''' + COALESCE(#myParameter1, 'DEFAULT') + ''',
#param2 = ' + COALESCE(CAST(#myParameter2 AS VARCHAR(30)),'DEFAULT') + ' );';
SELECT #SQL;
Result:
select * from [qlik].udf_getStatistic( #param1 = 'foo', #param2 = DEFAULT );
From my understanding, I try this on SQL Server 2012,
CREATE PROCEDURE ToNullProc
(#i VARCHAR(20))
AS
BEGIN
PRINT 'you entered ' + #i
END
CREATE FUNCTION ToNullFun
(#i VARCHAR(20))
RETURNS #table TABLE (i VARCHAR(20))
AS
BEGIN
INSERT INTO #table
SELECT ('You entered ' + #i) a
RETURN
END
DECLARE #j VARCHAR(20) = 'Hi',
#QueryFun NVARCHAR(50) = N'',
#QueryProd NVARCHAR(50) = N''
IF #j IS NOT NULL
BEGIN
SET #QueryFun = N'select * from ToNullFun ('''+#j+''')'
SET #QueryProd = N'exec ToNullProc '''+#j+''''
END
ELSE BEGIN
SET #QueryFun = N'select * from ToNullFun ('+#j+')'
SET #QueryProd = N'exec ToNullProc '+#j+''
END
PRINT #queryfun
PRINT #queryprod
EXEC sp_executesql #queryfun
EXEC sp_executesql #queryprod
update for dynamic procedure and dynamic function :
create table #temp (Num int identity (1,1), NullVal int)
insert into #temp (NullVal) values (1),(null),(3)
alter proc ToNullProc (
#Operator varchar (max), #NullVal varchar (max)
) as
begin
declare #Query nvarchar (max) = N'select * from #temp where NullVal ' +
#Operator + #NullVal
-- print #query + ' ToNullProc print '
exec sp_executesql #query -- Here we run the select query from Proc
end
create function ToNullFun (
#Operator varchar (max), #NullVal varchar (max)
)
returns nvarchar (max)
as
begin
declare #Query nvarchar (max)
set #Query = N'select * from #temp where NullVal ' + #Operator + #NullVal
/*
I try to into to Table variable by using ITVF,
'insert into #table exec sp_executesql #query'.
But this type of insert is not allowed in ITVF.
*/
return #query
end
declare #NullVal varchar (max) = '1'
, #QueryFun nvarchar (max) = N''
, #QueryProd nvarchar (max) = N''
declare #FunResultTalbe table (
Query nvarchar (100)
) /* To store the result Funtion */
if #NullVal is not null
begin
set #QueryFun = N'select dbo.ToNullFun ('' = '','''+#NullVal+''')'
set #QueryProd = N'exec ToNullProc '' = '','''+#NullVal+''''
end
else begin
set #QueryFun = N'select dbo.ToNullFun ('' is null '','''')'
set #QueryProd = N'exec ToNullProc '' is null '','''''
end
print #queryfun + ' At start'
print #queryprod + ' At start'
exec sp_executesql #queryprod -- It calls Proc
insert into #FunResultTalbe
exec sp_executesql #queryfun -- It calls the Function and insert the query into the table.
set #QueryFun = (select top 1 * from #FunResultTalbe) -- Here we get the query from the table.
print #queryfun
exec sp_executesql #queryfun -- Here we run the select query. Which is dynamic
Result sets
-- Result of Procedure
Num NullVal
1 1
-- Result of Function
Num NullVal
1 1
Let me know, what did you got.

Executing dynamic query inside a scalar function sql server

I am trying to make a scalar function in SQL Server. I have coined up the select statement as follows:
SET #Statement1 = 'SELECT 1 FROM ' + #p_TableName +
' WHERE RegionTypeID = 1 AND RegionID = ' +
CONVERT (nvarchar (50), #p_RegionID)
Here #p_TableName is the name of the table (nvarchar (500)) and #p_RegionID is a uniqueidentifier.
I am now executing the above statement as follows:
EXEC #ReturnValue1 = #Statement1
WHERE #ReturnValue1 is int.
But when I call this function from elsewhere I get this error:
The name 'SELECT 1 FROM [PS].[Availability] WHERE RegionTypeID = 1 AND
RegionID = AF4C182C-F751-41AD-AA6A-20A50A7A38C8' is not a valid
identifier.
I need to know how I can call a dynamic sql select statement from within a scalar function.
You can create SP like below with output parameter:
CREATE PROCEDURE ProcNameGoesHere
#p_TableName nvarchar(500),
#p_RegionID uniqueidentifier,
#output int OUTPUT
AS
BEGIN
DECLARE #Statement1 nvarchar(max),
#ParmDefinition nvarchar(500)
SET #Statement1 = N'SELECT #someValue = 1 FROM ' + #p_TableName +
' WHERE RegionTypeID = 1 AND RegionID = ' +
CONVERT (nvarchar (50), #p_RegionID)
SET #ParmDefinition = N'#someValue int OUTPUT'
EXEC sp_executesql #Statement1, #ParmDefinition, #output=#someValue OUTPUT
RETURN;
END
Then you can call it like this:
DECLARE #output int
EXEC ProcNameGoesHere '[PS].[Availability]','AF4C182C-F751-41AD-AA6A-20A50A7A38C8', #output OUTPUT
SELECT #output
Or:
IF ISNULL(#output,0) = 1
BEGIN
--Do something here
END

Creating view from multiple databases linked by columns with db name

Hi I need to create a view or stored procedure that combines data and returns a result set from 3 different databases on the same server using a column that holds a schema (db) name.
For Example on the first DB I have this table:
CREATE TABLE [dbo].[CloudUsers](
ID int IDENTITY(1,1) NOT NULL,
Username nvarchar(50) NULL,
MainDB nvarchar(100) NULL
) ON [PRIMARY]
Each CloudUser has a separate DB so next now I need to fetch the data from the User database using the MainDB name. The data I need is always 1 row cause I'm using aggregate functions / query.
So in the User MainDB let's say I have this table.
CREATE TABLE [dbo].[CLIENT](
ID int NOT NULL,
Name nvarchar(50) NULL,
ProjectDBName [nvarchar](100) NULL
CreationDate datetime NULL
) ON [PRIMARY]
And I query like:
select min(CreationDate) from MainDB.Client
The same Idea for the Client I need to fetch even more data from a 3rd database that points to the Client ProjectDBName. Again it's aggregate data:
select Count(id) as TotalTransactions from ProjectDBName.Journal
My final result should have records from all databases. It's readonly data that I need for statistics.
Final result set example:
CloudUsers.Username, MainDB->CreationDate, ProjectDBName->TotalTransaction
How can I achieve that ?
This is not easy - and without a schema and sample data, I can't give you a precise answer.
You need to iterate through each client, and use dynamic SQL to execute a the query against the mainDB and projectDB join. You can either do that in one gigantic "union" query, or by creating a temporary table and inserting the data into that temporary table, and then selecting from the temp table at the end of the query.
For you who are curious of how to solve this issue I have found my own solution using some cursors + dynamic and a simple table variable, enjoy.
ALTER PROCEDURE CloudAnalysis as
DECLARE #objcursor cursor
DECLARE #innercursor cursor
DECLARE #userid int
,#maindb nvarchar(100)
,#clientid int
,#name nvarchar(50)
,#projdb nvarchar(100)
,#stat nvarchar(50)
,#sql nvarchar(max)
,#vsql nvarchar(max)
,#rowcount int
DECLARE #result table(userid int,clientid int,maindb nvarchar(100),name nvarchar(50),projdb nvarchar(100),stat nvarchar(50))
SET #objcursor = CURSOR FORWARD_ONLY STATIC FOR SELECT c.id,c.maindb,u.client_id FROM dbo.ClientUsers c join dbo.UserClients u on c.id = u.user_id open #objcursor
FETCH NEXT FROM #objcursor INTO #userid,#maindb,#clientid
WHILE (##FETCH_STATUS=0)
BEGIN
IF (EXISTS (SELECT name
FROM master.dbo.sysdatabases
WHERE ('[' + name + ']' = #maindb
OR name = #maindb)))
BEGIN
set #sql = N'SELECT #name = c.name,#projdb=c.ProjectDBName FROM ' + #maindb + '.dbo.CLIENT c WHERE c.id = ' + cast(#clientid as nvarchar)
EXECUTE sp_executesql #sql, N'#name NVARCHAR(50) OUTPUT,#projdb NVARCHAR(100) OUTPUT',
#name = #name OUTPUT
,#projdb = #projdb OUTPUT
SELECT #rowcount = ##ROWCOUNT
IF #rowcount > 0
BEGIN
--print ' client: ' + cast(#clientid as nvarchar)+
--':' + #name + ' projdb: ' + #projdb
IF (EXISTS (SELECT name
FROM master.dbo.sysdatabases
WHERE ('[' + name + ']' = #projdb
OR name = #projdb)))
BEGIN
SET #sql = N'SELECT #stat = j.stat FROM ' + #projdb + '.dbo.JournalTransaction j'
EXECUTE sp_executesql #sql
,N'#stat NVARCHAR(50) OUTPUT'
,#stat = #stat OUTPUT
END
INSERT INTO #result (userid,clientid,maindb,name,projdb,stat)
VALUES (#userid,#clientid,#maindb,#name,#projdb,#stat)
END
END
FETCH NEXT FROM #objcursor INTO #userid,#maindb,#clientid
END
CLOSE #objcursor
DEALLOCATE #objcursor
SELECT * FROM #result

sql server 2008 create columns using a while

I need to create about 300 columns for a table and I don't want to to it manually.
How can I do this?
I want to have columns like
Bigint1..to..Bigint60
Text1 ..to..Text60
and so on.
IF (NOT EXISTS (SELECT *
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'dbo'
AND TABLE_NAME = 'mytbl'))
begin
create table OBJ_AttributeValues(
ObjectID numeric(18,0) not null
);
end
else
begin
DECLARE #A INT
set #A = 1;
WHILE(#A <=60)
BEGIN
alter table OBJ_AttributeValues
add ...............................
set #A = #A+1;
END
end
What should I write instead of "..."?
You will need to use dynamic SQL for that, something like
DECLARE #SSQL VARCHAR(1000)
DECLARE #A INT
set #A = 1;
WHILE(#A <=60)
BEGIN
SET #SSQL = 'alter table OBJ_AttributeValues add Bigint' + CAST(#A as varchar) + ' bigint'
EXEC (#SSQL)
set #A = #A+1;
END
This isn't really a good idea, you should take the time to write the sql or just copy-paste the columns from Excel or something like that. You also shouldn't be using the TEXT data type, is deprecated and filled with restriction (use VARCHAR(MAX) instead if you need). That said, here is a way using dynamic SQL:
DECLARE #BigintCols NVARCHAR(MAX), #TextCols NVARCHAR(MAX)
DECLARE #Query NVARCHAR(MAX)
SET #BigintCols = ''
SET #TextCols = ''
SELECT #BigintCols = #BigintCols + N'Bigint' + CAST(number AS NVARCHAR(2)) + N' BIGINT,',
#TextCols = #TextCols + N'Text' + CAST(number AS NVARCHAR(2)) + N' TEXT,'
FROM master..spt_values
WHERE type = 'P'
AND number BETWEEN 1 AND 60
ORDER BY number
SET #Query = '
CREATE TABLE OBJ_AttributeValues(ObjectID numeric(18,0) not null,'+#BigintCols+
LEFT(#TextCols,LEN(#TextCols)-1)+')'
EXECUTE sp_executesql #Query
Oh, you should probably read about dynamic sql first.

Resources