Inner join within Dynamic SQL is not working - tsql

I have a query within a SP like below
declare #Sql nvarchar(max);
SET #Sql= N' select a.ultimatedunsnumber,a.account,a.AccountSubSegment
into #channel_shift
from #temp_p06 a inner join #temp_p02 b
on a.ultimatedunsnumber=b.UltimateDunsNumber
and a.accountchannel<>b.accountchannel ';
print #sql
EXECUTE sp_executesql #Sql;
And the #temp_06 and #temp_02 tables are created dynamically within the SP and they got created successfully.
But the above query is throwing an error:
Msg 4145, Level 15, State 1, Line 66 An expression of non-boolean type
specified in a context where a condition is expected, near 'ultimate'.

Related

An expression of non-boolean type specified in a context where a condition is expected, near 'tblProje'

I am getting this error message when running this sql statement in ssms:
An expression of non-boolean type specified in a context where a condition is expected, near 'tblProje'
This is the statement itself:
PRINT 'Updating FileSetId data from Table Project to Table tblProject'
DECLARE #SQL NVARCHAR(100)
SET #SQL = 'UPDATE tblProject set tblProject.ProjectFileSetId = Project.FileSetId
FROM Project
WHERE tblProject.AccountingProject = Project.Project_Id'
IF EXISTS(select * from INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'Project' AND COLUMN_NAME = 'FileSetId')
BEGIN
execute sp_executesql #SQL
END
GO
I am trying to make the statement so that it can run as many times as possible. Basically checking to make sure that a column exists before trying to update from it. I cannot tell where this error is coming from
If you take your query and look at the length, you will see an issue:
DECLARE #SQL NVARCHAR(100)
SET #SQL = 'UPDATE tblProject set tblProject.ProjectFileSetId = Project.FileSetId
FROM Project
WHERE tblProject.AccountingProject = Project.Project_Id'
select len(#sql)
select len('UPDATE tblProject set tblProject.ProjectFileSetId = Project.FileSetId
FROM Project
WHERE tblProject.AccountingProject = Project.Project_Id')
Your variable assignment is cutting off 41 chars at the end so it is not valid SQL to execute when you run sp_executesql. Change your variable to something like NVARCHAR(4000) or NVARCHAR(MAX) and it will work.
PRINT 'Updating FileSetId data from Table Project to Table tblProject'
DECLARE #SQL NVARCHAR(MAX)
SET #SQL = 'UPDATE tblProject set tblProject.ProjectFileSetId = Project.FileSetId
FROM Project
WHERE tblProject.AccountingProject = Project.Project_Id'
IF EXISTS(select * from INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'Project' AND COLUMN_NAME = 'FileSetId')
BEGIN
execute sp_executesql #SQL
END
GO

Stored procedure to build new queries and a cursor to help execute them - SQL

I am trying to build a stored procedure that takes in values of
#field_name
#some_rule
#from_table
#to_table
and builds up a query. Below is the code from my Stored Procedure:
CREATE PROCEDURE spBuildQuery
#field_name nvarchar(max), -- Will take field name as input
#some_rule nvarchar(max), -- Will take Some rule as a command/input from user
#from_table nvarchar(max), --to take value of table from which value to be taken
#to_table nvarchar(max), --Table where the results should be stored
#final_query nvarchar(max) OUTPUT --Output of final query
AS
IF #some_rule = 'Remove blank rows'
BEGIN
SELECT #final_query = 'SELECT * into temp1 FROM '+#from_table + ' WHERE '+ #field_name+ ' IS NOT NULL'
END
ELSE IF #some_rule = 'Rule2'
BEGIN
SELECT #final_query = 'SELECT * into temp1 FROM'+ #from_table + 'WHERE '+ #field_name+ ' IS RULE2'
END
ELSE
BEGIN
SELECT #final_query = 'Missing Value(s)'
END
--Executing the query by parsing #final_query value into #query and priting it.
DECLARE #query nvarchar(max)
EXECUTE spBuildQuery 'A Field', 'Rule2', 'Table 1', #query OUTPUT
PRINT #query
EXECUTE sp_executesql #query
My intention is to build queries based on user input like: Rules the user wants to implement what field should the rules be applied to and then display the result of that query onto a table, then that Table gets overwritten as new queries are developed. This is my intention, as another approach I was thinking is to save the built up queries into a table column and execute each query line by line using a cursor.
How can I:
a) store the built up queries into a new TEMP table?
b) execute each query using the Cursor (or any other efficient way)?

MS T-SQL 2008: Executing an openrowset sql string will not work

Running this code
DECLARE #SQL VARCHAR(2500) =
'''SELECT z.* from openrowset(''''SQLNCLI'''',''''Server=server;UID=user;PWD=pwd;'''',
''''SELECT distinct x.PackageName
FROM [dw].[dbo].[dex] x
JOIN [dw].dbo.log l on l.executionid = x.SSISExecutionGUID '''') z''' EXECUTE (#SQL)
Issues a syntax error Incorrect syntax near 'select z.*
from openrowset('SQLNCLI', 'Server=server;UID=user;PWD=pw;',
'SELECT distinct x.PackageN'.
if I remove the parens from the (#SQL) the error changes to this:
The name ''select z.*
from openrowset(''SQLNCLI'', ''Server=server;UID=user;PWD=pwd;'',
''SELECT distinct x.PackageName
FROM [dw].[dbo].[dex] x join [dw].dbo.log l on l.executionid = x.SSISExecutionGUID ''
) z'' is not a valid identifier.
and funniest of all, if i change Execute to Print, then manually take the printed result and wrap EXECUTE around it, it works as expected and gets me my results.
I'm thinking it's some crazy single quote issue, but I can't see it.
Anyone have any ideas?
I just took the output of the print and pasted that into the variable assignment instead and it appears to work (at least as far as I can tell this end - at least it doesn't give any syntax errors)
DECLARE #SQL VARCHAR(2500) = '
SELECT z.* from openrowset(''SQLNCLI'',''Server=server;UID=user;PWD=pwd;'',
''SELECT distinct x.PackageName FROM [dw].[dbo].[dex] x
JOIN [dw].dbo.log l on l.executionid = x.SSISExecutionGUID '') z'
EXECUTE (#SQL)

Dynamic SQL, sp_executesql, and rebuilding the dynamic sql statement - Part 1

Part 1: In his article, "Dynamic Search Conditions in T-SQL...for SQL 2005 and Earlier", Erland Sommarskog gives an example of how to use dynamic sql with sp_executesql.
http://www.sommarskog.se/dyn-search-2005.html#sp_executesql
SELECT #sql = -- 19
'SELECT o.OrderID, o.OrderDate, od.UnitPrice, od.Quantity, -- 20
c.CustomerID, c.CompanyName, c.Address, c.City, -- 21
c.Region, c.PostalCode, c.Country, c.Phone, -- 22
p.ProductID, p.ProductName, p.UnitsInStock, -- 23
p.UnitsOnOrder -- 24
FROM dbo.Orders o -- 25
JOIN dbo.[Order Details] od ON o.OrderID = od.OrderID -- 26
JOIN dbo.Customers c ON o.CustomerID = c.CustomerID -- 27
JOIN dbo.Products p ON p.ProductID = od.ProductID -- 28
WHERE 1 = 1' -- 29
-- 30
IF #orderid IS NOT NULL -- 31
SELECT #sql = #sql + ' AND o.OrderID = #xorderid' + -- 32
' AND od.OrderID = #xorderid' -- 33
-- 34
IF #fromdate IS NOT NULL -- 35
SELECT #sql = #sql + ' AND o.OrderDate >= #xfromdate' -- 36
etc...
So, as you build your dynamic sql statement, it makes sense if you have to run just one sp_executesql for your #sql variable.
However, let's suppose you've built your #sql, and returned the filtered records you want returned, but you also want a COUNT of the records returned.
What would be the best way to go about doing this?
Would you have to declare another variable, #sql_2, whose build would be nearly identical to #sql, except the SELECT statement in #sql_2 would do a SELECT COUNT(*)... instead of a SELECT col1, col2, col3?
Or is there a better approach to take?
String the SQL statements together separated by semicolons. Here is a working example that returns the tables in your database that start with the letter "A" and the count.
First the simple version. This returns 2 result sets, the second one being the count.
declare #findTables nvarchar(256)
set #findTables = N'A%'
declare #sql nvarchar(max)
set #sql = N'set nocount on; '+
'select * from sys.tables where name like '''+#findTables+''';'+
'select ##RowCount as [RowCount];';
execute sp_executesql #sql
Now a version where a variable gets valued with the count for when you need to use it later in the stored proc.
declare #findTables nvarchar(256)
set #findTables = N'A%'
declare #sql nvarchar(max)
declare #ParmDefinition nvarchar(500);
declare #rowCount int
set #sql = N'set nocount on;
select * from sys.tables where name like #findTablesParm;
select #rowCountParm = ##rowcount;
select #rowCountParm as [RowCount];';
SET #ParmDefinition = N'#findTablesParm nvarchar(256),
#rowCountParm int OUTPUT';
execute sp_executesql #sql,
#ParmDefinition,
#findTablesParm=#findTables,
#rowCountParm=#rowCount OUTPUT
After this runs you should see 2 result sets, the second one will contain the RowCount and the variable #rowCount will also contain the row count.

How to handle an empty result set from an OpenQuery call to linked analysis server in dynamic SQL?

I have a number of stored procedures structured similarly to this:
DECLARE #sql NVARCHAR(MAX)
DECLARE #mdx NVARCHAR(MAX)
CREATE table #result
(
[col1] NVARCHAR(50),
[col2] INT,
[col3] INT
)
SET #mdx = '{some dynamic MDX}'
SET #sql = 'SELECT a.* FROM OpenQuery(LinkedAnalysisServer, ''' + #mdx + ''') AS a'
INSERT INTO #result
EXEC sp_executesql #sql
SELECT * FROM #result
This works quite well when results exist in the cube. However, when the OpenQuery results are empty, the INSERT fails with this error:
Column name or number of supplied
values does not match table
definition.
My question is, what is the best way to handle this scenario? I'm using the results in a static report file (.rdlc), so the explicit typing of the temp table is (I'm pretty sure) required.
Use TRY/CATCH in your stored procedure, you'll notice there is a specific error number for your problem, so check the error number and if it is that, return an empty result set. As you already have the table defined that'll be easier.
PseudoCode looks something like this:
SET #mdx = '{some dynamic MDX}'
SET #sql = 'SELECT a.* FROM OpenQuery(LinkedAnalysisServer, ''' + #mdx + ''') AS a'
BEGIN TRY
INSERT INTO #result
EXEC sp_executesql #sql
END TRY
BEGIN CATCH
IF ERROR_NUMBER <> 'The error number you are seeing'
BEGIN
RAISERROR('Something happened that was not an empty result set')
END
END CATCH
SELECT * FROM #result
You'll want to check for that particular error, so that you don't just return empty result sets if your SSAS server crashes for example.
There is another solution to this issue, similar to the accepted answer, which involves using an IF statement instead of TRY...CATCH.
http://www.triballabs.net/2011/11/overcoming-openquery-mdx-challenges/
IF (SELECT COUNT(*)
FROM OPENQUERY("SSAS1",
'SELECT [Measures].[Target Places] ON COLUMNS
FROM [ebs4BI_FactEnrolment]
WHERE [DimFundingYear].[Funding Year].&[17]')) > 0
EXEC sp_executesql N'SELECT CONVERT(varchar(20),
"[DimPAPSCourse].[Prog Area].[Prog Area].[MEMBER_CAPTION]")
as ProgArea,
convert(float, "[Measures].[Target Places]") as Target
FROM OPENQUERY("SSAS1",
''SELECT [Measures].[Target Places] ON COLUMNS,
[DimPAPSCourse].[Prog Area].[Prog Area] ON ROWS
FROM [ebs4BI_FactEnrolment]
WHERE [DimFundingYear].[Funding Year].&[17]'')'
ELSE
SELECT '' as ProgArea, 0 as Target
WHERE 1=0