SQL query not showing columns in DataSet in Visual Studio - sql

I have a stored procedure in SQL Server 2008. I declare an #query param via DECLARE #query NVARCHAR(MAX), I then set this #query according to the type of data sent in and then I use exec [sys].[sp_executesql] #query to execute the stored procedure.
The problem I'm having is that I'm using a DataSet in Visual Studio, that links to this stored procedure (used on a report).
When I do my stored procedure in this manner (with the #query), then the dataset does not pick up the column data to show. I had to create the stored procedure this way (with #query), because I need the where clause to be different depending on the data sent in.
My code:
CREATE PROCEDURE [dbo].[p_Test_GetFooData]
#pName VARCHAR(250) = '',
#pID INT = NULL
AS
BEGIN
DECLARE #query NVARCHAR(MAX)
SET #query = 'SELECT FOO.FirstName, FOO.LastName
FROM Test.FooOne AS FOO'
IF ( #pName = '--- SELECT ---' )
BEGIN
SET #query = #query + ' WHERE FOO.ID = '
+ CONVERT(VARCHAR(50), #pID) + ''
END
ELSE
BEGIN
SET #query = #query + ' WHERE FOO.ID = '
+ CONVERT(VARCHAR(50), #pID) + ' AND
PP.FirstName + LIKE ''%' + #pName
+ '%'' '
END
EXEC [sys].[sp_executesql] #query
END
I have tested the query and it returns the correct data when I run the stored procedure. When I don't use SET #query = 'SELECT STATEMENT' EXEC #query then the dataset works as it should.
Any help will be appreciated.

Another option is to write the query in a different way eg.
SELECT FOO.FirstName,
FOO.LastName
FROM Test.FooOne AS FOO
WHERE FOO.ID = #pID
and PP.FirstName LIKE case when #pName = '--- Select ---' then PP.FirstName else '%' + #pName + '%' end
This will always compare Foo.ID to #pID
and will either compare pp.FirstName to itself (always returning true) or wil

Related

Like in dynamic function

The code below works well. I however have issues trying to turn it into a like statement that I need some assistance with
CREATE PROCEDURE [dbo].[searcher]
#deliverer nvarchar (100)
AS
BEGIN
DECLARE #sql nvarchar(1000)
SET #sql = 'SELECT location, deliverer, charger FROM Store where 1=1'
IF (#deliverer IS NOT NULL)
SET #sql = #sql + ' and deliverer =#pt'
DECLARE #t1 as TABLE
(
location varchar(1000),
deliverer varchar(100),
charger varchar(100)
)
INSERT INTO t1
EXEC sp_executesql #sql,
N'#pt nvarchar(100)',
#pt=location
SELECT * FROM t1
END
So far, I have tried the code below but with not much success
DECLARE #pt nvarchar (100)
SET #pt = '%' + #pt + '%'
IF (#deliverer IS NOT NULL)
SET #sql = #sql + ' and deliverer like #pt'
I have also tried;
DECLARE #pt nvarchar (100)
IF (#deliverer IS NOT NULL)
SET #sql = #sql + ' and deliverer like ''% + #pt + %'''
If your stored procedure parameter is #deliverer and your dynamic SQL parameter is #pt, I believe your sp_executesql execution should assign the parameter as #pt = #deliverer.
As for adding wildcards, you can either add them before the call with
SET #deliverer = '%' + #deliverer + '%'
or add them in the dynamic SQL with
SET #sql = #sql + ' and deliverer like ''%'' + #pt + ''%'''
Note the doubled up quotes around the %. The variable #pt is not quoted

Assign result from dynamic SQL in a parameter to another parameter

I'm having to build my query dynamically, firstly, it gets the maxlogid from the log, and appends this to the temporary table name. Then it does a COALESCE to return the distinct values into a string.
However, the output of the string, I want to have in a parameter, so I can use it again later on within a dynamic sql query.
Here is my code;
DECLARE #maxLogId VARCHAR(10)
SELECT #maxLogId = (SELECT Max(id) FROM dbo.tLog)
DECLARE #PolicyTempTable VARCHAR(100)
SET #PolicyTempTable = '##tPols' + #maxLogId
DECLARE #emailParm NVARCHAR(1000)
SET #emailParm = N'DECLARE #email VARCHAR(MAX)
SELECT COALESCE(#email+'','' ,'''') + '''''''''''' + EMAIL + ''''''''''''
FROM (SELECT DISTINCT EMAIL FROM ' + #PolicyTempTable + ') d'
EXEC sp_executesql #emailParm
The results are returned as follows;
"abc#a.co.uk",""abc#b.co.uk"
I want to be able to write the sp_executesql into a seperate parameter, so I can use for a dynamic query like below;
DECLARE #StrSQLEmail VARCHAR(8000)
SET #StrSQLEmail = 'SELECT * FROM OPENQUERY(ATOM,''Select * from ATOMS.EMAILS WHERE EMAIL IN (' + '' EXEC sp_executesql #emailParm + '' + ')'')'
However, I can't use the sp_executesql within my dynamic query.
You can use parameters with sp_executesql
DECLARE #emailParm NVARCHAR(1000)
DECLARE #emailOut NVARCHAR(MAX)
SET #emailParm = N'SELECT COALESCE(#email+'','' ,'''') + '''''''''''' + EMAIL + ''''''''''''
FROM (SELECT DISTINCT EMAIL FROM ' + #PolicyTempTable + ') d'
EXEC sp_executesql #emailParm, N'#email VARCHAR(1000) OUTPUT', #email = #emailOut OUTPUT
Then you can build your second dynamic sql
DECLARE #StrSQLEmail VARCHAR(8000)
SET #StrSQLEmail = 'SELECT * FROM OPENQUERY(ATOM,''Select * from ATOMS.EMAILS WHERE EMAIL IN (' + #emailOut + ')'')'

Is it possible to set a variable for a stored procedure as column type?

It seems like a simple enough event you just declare a variable you are passing to your stored procedure as column. I am needing to pass a column name to my stored procedure that will be used in my query. Is it possible to declare it so I can use it as a column name or is there some way I can convert say a string to column type?
where Line1AStatus = 1
I need to be able to pass to my stored procedure what that number is in Line Status. I have tried these methods so far. Thank you for your help.
where Line + #LineNum + AStatus = 1
where 'Line' + #LinNum + 'AStatus' = 1
not with standard SQL but you can with dynamic sql
DECLARE #SQL nvarchar(max)
SELECT #SQL = 'SELECT * FROM table where ''Line' + CAST(#LinNum AS NVARCHAR) + 'AStatus'' = 1'
exec sp_executeSQL #sql
Example of a while loop
DECLARE #SQL nvarchar(max), #LinNum int
SELECT #LinNum = 1
WHILE(#LinNum <= 5)
BEGIN
SELECT #SQL = 'SELECT * FROM table where ''Line' + CAST(#LinNum AS NVARCHAR) + 'AStatus'' = 1'
exec sp_executeSQL #sql
SELECT #LinNum = #LinNum + 1
END

SQL Dynamic Query String Breaks When Variable Contains Single Quote

I have a SQL query string that is like this:
DECLARE #sql varchar(max)
SET #sql = ' INSERT INTO ' + #tempTable1 +
' SELECT 0 as Type1, 0 as Type2, ' +
'''' + #name + ''' as CompanyName ' +
' FROM #tempTable2 tt2'
The query runs fine except for two names that happen to contain a single quote (ex: Pete's Corner). When either one of these names becomes part of the query it breaks the query string. I thought the easiest thing to do would be to replace the single quote like this replace(#name,'''','') but it doesn't work because I'm already in a string and so its affecting the rest of the statement. Altering the table itself is not an option unfortunately.
How can I replace or remove these single quotes?
Addition: I apologize, I did not include the part where #name is actually being populated from another database table by a join so setting the value of #name before the string is created I think would be difficult for me.
Why do you need to do this at all? You should be passing strong parameters to sp_executesql instead of munging all of your parameters into a single string and using EXEC(). More info on that here.
DECLARE #sql NVARCHAR(MAX), #name NVARCHAR(32);
SET #name = 'Pete''s Corner';
SET #sql = 'INSERT INTO ' + #tempTable1 +
' SELECT 0 as Type1, 0 as Type2, #name as CompanyName ' +
' FROM #tempTable2 tt2';
EXEC sp_executesql #sql, N'#name NVARCHAR(32)', #name;
I presume the #name parameter actually gets populated from elsewhere, and if using proper parameterization you shouldn't have to deal with escaping the '.
Now I'm not quite sure what #tempTable1 is supposed to represent, or if you can access #tempTable2 from this scope, but whenever you find yourself running a replace that requires '''' or '''''' (or both), you should ask yourself if maybe there's a better way.
I think this should do it:
DECLARE #sql varchar(max)
SET #sql = ' INSERT INTO ' + #tempTable1 +
' SELECT 0 as Type1, 0 as Type2, ' + ''''+
replace( #name ,'''','''''')+''''+' as CompanyName
FROM #tempTable2 tt2'
You can use sp_executesql system procedure. sp_executesql will allow you to call dynamic SQL with #name parameter instead of embedding it into the SQL.
DECLARE #sql nvarchar(max),
#name varchar(50)
SET #name = 'qwe'''
SET #sql = 'INSERT INTO ' + #tempTable1 +
' SELECT 0 as Type1, 0 as Type2, ' +
'#name as CompanyName ' +
'FROM #tempTable2 tt2'
--PRINT #sql
EXEC sp_executesql #sql, N'#name varchar(50)', #name

Using Dynamic SQL in User Defined Function to return string (not modify data)

Our document storage application has a unique database for each of our clients which are almost identical to each other, but one table DocumentIndexes is unique for each client and can have any number of columns and types.
I am trying to create a generic function (within our "master" database called MYAPP_MASTER) that I can call and simply pass in a database name and a document ID value and get back the column names and values from from the specified database's DocumentIndexes table. Because I have to pass in the database name, I have to generate the selection SQL dynamically and call sp_executesql.
I have the following code which polls the INFORMATION_SCHEMA.COLUMNS table to determine the columns needed and it works just fine in a stored procedure, but I hate having to copy all this code in every stored procedure that needs these to retrieve these dynamic column values. I would rather have one function that returns the string value of these columns regardless of database and have the function exist once in our MYAPP_MASTER database. Again, this code works, but SQL won't allow me to put it into a function. Is there anyway around this?
USE MYAPP_MASTER
GO
DECLARE #DatabaseName varchar(255)
DECLARE #DocumentId int
SET #DatabaseName = 'SAMPLE_CLIENT_DB'
SET #DocumentId = 1234
DECLARE #DynamicIndexes nvarchar(max)
DECLARE #DynamicIndexesParam nvarchar(max)
DECLARE #DynamicIndexesSql nvarchar(max)
SET #DynamicIndexesParam = '#Indexes varchar(max) OUTPUT'
SET #DynamicIndexesSql = 'SELECT #Indexes = COALESCE(#Indexes + ''+ '''', '', '''') + CAST(COLUMN_NAME as varchar(max)) + '': '''''' + '' + CASE WHEN DI.'' + COLUMN_NAME + '' IS NOT NULL THEN CAST(DI.'' + COLUMN_NAME + '' as varchar(max)) ELSE '''''''' END '' FROM ' + #DatabaseName + '.INFORMATION_SCHEMA.COLUMNS WHERE table_name = ''DocumentIndexes'' AND COLUMN_NAME <> ''DocumentID''; '
EXEC sp_executesql #DynamicIndexesSql, #DynamicIndexesParam, #Indexes = #DynamicIndexes OUTPUT
SET #DynamicIndexes = '''' + #DynamicIndexes
DECLARE #SelectionSql nvarchar(max)
SET #SelectionSql = 'SELECT ' + #DynamicIndexes + ' as DocumentIndexes FROM ' + #DatabaseName + '..Document D LEFT OUTER JOIN ' + #DatabaseName + '..DocumentIndexes DI ON D.DocumentId = DI.DocumentId WHERE D.DocumentID = ' + CAST(#DocumentId as varchar(10))
EXEC sp_executesql #SelectionSql
If the SAMPLE_CLIENT_DB datababase DocumentIndexes table has columns for Name, Office and Classification, this code will return a simple string that looks like the following:
Name: Foo, Office: Bar, Classification: 123
You can't run an Exec command inside a SQL function, but you could use a stored procedure with an output variable assuming the DocumentIndexes table is unique at the DocumentID level.
Create Proc DocID_DocIndexes #retval Varchar(Max) Output
As
...
(Your code logic minus last two lines)
...
-- Populate your dynamic SQL into a variable to assign it to the output variable
SET #SelectionSql = 'SELECT #result = ' + #DynamicIndexes + ' as DocumentIndexes FROM ' + #DatabaseName + '..Document D LEFT OUTER JOIN ' + #DatabaseName + '..DocumentIndexes DI ON D.DocumentId = DI.DocumentId WHERE D.DocumentID = ' + CAST(#DocumentId as varchar(10))
EXEC sp_executesql #SelectionSql, N'#result Varchar(Max) Output', #result = #retval Output
Return