How to cast a query with CTE as nvarchar(max)? - sql-server

Normally, we can cast a single record query to nvarchar(max). For example:
DECLARE #result NVARCHAR(MAX) = N'';
SELECT
#result = #result + (CAST((SELECT TOP(3) name AS td
FROM
sys.databases
FOR XML PATH ('')) AS NVARCHAR(MAX)));
SELECT #result
But how can I do the same thing when the query has CTE? The query still returns a single row. For example:
DECLARE #result NVARCHAR(MAX) = N'';
SELECT
#result = #result + (CAST((WITH d AS
(SELECT name FROM sys.databases)
SELECT TOP(3) name AS td
FROM d
FOR XML PATH ('')) AS NVARCHAR(MAX)));
SELECT #result
When I execute it, I got the following errors:
Msg 156, Level 15, State 1, Line 7
Incorrect syntax near the keyword 'WITH'.
Msg 319, Level 15, State 1, Line 7
Incorrect syntax near the keyword 'with'. If this statement is a common table expression, an xmlnamespaces clause or a change tracking context clause, the previous statement must be terminated with a semicolon.
Msg 102, Level 15, State 1, Line 8
Incorrect syntax near ')'
I know I can use a derived table or subquery etc. But in my case, the query is very complex and it has several CTEs in it, which I don't want to touch.

Your CTE definition should not be on select statement:
DECLARE #result NVARCHAR(MAX) = N'';
WITH d AS (SELECT name FROM sys.databases)
SELECT #result = #result + (CAST((SELECT TOP(3) name AS td FROM d FOR XML PATH ('')) AS NVARCHAR(MAX)));
SELECT #result

Related

Set a Value in Verbal using sql

I want to set "InOperator" value in a Verbal. This is my select Query.
DECLARE #i nvarchar(Max); set #i = '619, 618, 620, 2162, 2173, 3613, 2090';
select * from tbl_PharmacypurDetail where ItmCode in (CAST(#i as bigint))
Result
Msg 8114, Level 16, State 5, Line 2
Error converting data type nvarchar to bigint.
You can use STRING_SPLIT to splits a string into rows of substrings, based on a specified separator character.
DECLARE #i nvarchar(Max); set #i = '619, 618, 620, 2162, 2173, 3613, 2090';
select * from tbl_PharmacypurDetail where ItmCode in (SELECT value FROM STRING_SPLIT(#i, ','))
You can use split function :
select tp.*
from tbl_PharmacypurDetail tp cross apply
dbo.splitfn(#i, ',') as t(val)
where t.val = tp.itemcode;
If you are working with SQL Server 2016 or higher then you can use STRING_SPLIT.
You can use something like this instead in case your server doesn't support STRING_SPLIT:
DECLARE #i nvarchar(Max);
SET #i = '619, 618, 620, 2162, 2173, 3613, 2090';
SELECT *
FROM tbl_PharmacypurDetail
WHERE CHARINDEX(',' + CONVERT(NVARCHAR(MAX), ItmCode) + ',', ',' + REPLACE(#i, ' ', '') + ',') > 0

Unclosed quotation mark after the character string ')' - OPENQUERY

I have the following query, executed with OPENQUERY :
DECLARE #DOMAIN NVARCHAR = N'XXX'
DECLARE #QUERY NVARCHAR(MAX)= '
SELECT * FROM OPENQUERY( [XX\XX],''
SELECT CONCAT(CONCAT([Firstname],''),[Lastname]) AS [Owner]
FROM [Employee] '')'
EXECUTE XX_executesql #QUERY
When I execute , I get this following error :
Msg 102, Level 15, State 1, Line 4 Incorrect syntax near ')'. Msg 105,
Level 15, State 1, Line 5 Unclosed quotation mark after the character
string ')'.
If you print the #Query value, you will see the error root. So if you run the following code:
DECLARE #DOMAIN NVARCHAR = N'XXX';
DECLARE #QUERY NVARCHAR(MAX)= '
SELECT * FROM OPENQUERY( [XX\XX],''
SELECT CONCAT(CONCAT([Firstname],''),[Lastname]) AS [Owner]
FROM [XXX].[dbo].[Employee] '')'
PRINT #QUERY
You will get the following result:
SELECT * FROM OPENQUERY( [XX\XX],'
SELECT CONCAT(CONCAT([Firstname],'),[Lastname]) AS [Owner]
FROM [XXX].[dbo].[Employee] ')
Now it is clear why SQL Server returns the
Unclosed quotation mark after..
To solve it you need to keep in mind that, in order to have a single quote mark in the output in a string variable, you need to put two single quote mark.
Now you need to rewrite it as below:
DECLARE #DOMAIN NVARCHAR = N'XXX';
DECLARE #QUERY NVARCHAR(MAX)= '
SELECT * FROM OPENQUERY( [XX\XX],''
SELECT CONCAT(CONCAT([Firstname],''''),[Lastname]) AS [Owner]
FROM [XXX].[dbo].[Employee] '')'
PRINT #QUERY
aforementioned query will produce:
SELECT * FROM OPENQUERY( [XX\XX],'
SELECT CONCAT(CONCAT([Firstname],''),[Lastname]) AS [Owner]
FROM [XXX].[dbo].[Employee] ')
You can now simply replace Print with EXECUTE command and execute it!
You are not escaping your string quotes.
If you want to include an ' inside an string, you have to write it twice ''
So, for example, CONCAT([Firstname],'') would have to be CONCAT([Firstname],'''')
See How do I escape a single quote in SQL Server?
PS: And as #TT. has commented, in this case you will probably need to re-escape your quotes inside the openquery scope, because the openquery call will escape them again.
So CONCAT([Firstname],'') would in fact have to be CONCAT([Firstname],'''''''')

Incorrect syntax near '=' in Exec statement

when I execute this:
declare #INP_ITBL_NM_SQL char (64)
Exec('
select '+#INP_ITBL_NM_SQL+' =
concat(LTRIM(RTRIM(a.db_schema_name)),LTRIM(RTRIM(b.Name)))
from '+#db_and_schema+' as a, '+#split_itbl+' as b
where b.ID = 2 and a.libname = (select c.Name from
'+#split_itbl+' as c where c.ID = 1)
')
I get the following error:
Msg 102, Level 15, State 1, Line 2 Incorrect syntax near '='.
The variables inside the select statement are temporary tables which (need to) change their name every run.
Thanks for the help!
You are getting that error because you are trying to set the value of a local variable to a value from within dynamic SQL. So when you print out that SQL text it looks something like:
SELECT = concat…
You should do this using output parameters with sp_executesql. Something like the following:
DECLARE #SQL nvarchar(max)
DECLARE #ParamDef nvarchar(200)
DECLARE #INP_ITBL_NM_SQL varchar(100) = ''
SET #ParamDef = N'#INP_ITBL_NM_SQL_OUTPUT varchar(100) OUTPUT';
SET #SQL = N'select #INP_ITBL_NM_SQL_OUTPUT = concat(LTRIM(RTRIM(a.db_schema_name)),LTRIM(RTRIM(b.Name)))
from '+ #db_and_schema+ ' as a, ' + #split_itbl +' as b
where b.ID = 2 and a.libname = (select c.Name from
'+ #split_itbl +' as c where c.ID = 1)'
EXEC sp_executesql #SQL, #ParamDef, #INP_ITBL_NM_SQL_OUTPUT=#INP_ITBL_NM_SQL OUTPUT;
SELECT #INP_ITBL_NM_SQL

Inserting content of SQL query in XML using FOR XML PATH

I wrote a stored procedure that returns nvarchar variable that contains some generated SQL query, and second procedure, that generates XML using FOR XML PATH.
I want to modify my procedure that generates XML and add content of my generated query from first procedure into generated XML.
Part of my procedure that generates XML:
SELECT #SQLStr = 'SELECT';
DECLARE #tmp varchar(100), #tmpkod varchar(max);
DECLARE c CURSOR LOCAL READ_ONLY FOR
SELECT tableName, tableCode FROM #TableNames
OPEN c
FETCH NEXT FROM c INTO #tmp, #tmpkod;
WHILE ##FETCH_STATUS = 0
BEGIN
SELECT #i = #i - 1;
SELECT #SQLStr = #SQLStr + '(SELECT TOP 10 * FROM ' + #tmp + ' FOR XML PATH(''row''), TYPE) AS ' + #tmp + ',
'
EXEC GenerujSelectazXML #tmp, #tmpcode output;
SELECT #SQLStr = #SQLStr + '(SELECT ' + #tmpCode + ' FOR XML PATH (''row''), TYPE) AS ' + #tmp + '_TEST'
SELECT #tmpcode
IF (#i <> 0) SELECT #SQLStr = #SQLStr + ',
'
ELSE SELECT #SQLStr = #SQLStr + '
'
FETCH NEXT FROM c INTO #tmp, #tmpkod;
END
CLOSE c; DEALLOCATE c;
SELECT #SQLStr = #SQLStr + 'FOR XML PATH(''''), ROOT(''root'')';
EXEC (#SQLStr)
I cannot simply put content of a query into XML, because it contains some special characters like " < ", " > ", and they are introducing/ending xml tags.
So i thought that putting query command into XML comment will solve my problem.
I tried this:
SELECT #SQLStr = '<!--' + #tmpCode + '-->';
and it didn't help, I got error:
Msg 102, Level 15, State 1, Line 3
Incorrect syntax near '<'.
Msg 137, Level 15, State 1, Line 4
Must declare the scalar variable "#xml".
Msg 137, Level 15, State 2, Line 216
Must declare the scalar variable "#xml".
Msg 156, Level 15, State 1, Line 217
Incorrect syntax near t he keyword 'FOR'.
Msg 137, Level 15, State 1, Line 219
Must declare the scalar variable "#xml".
Msg 137, Level 15, State 2, Line 416
Must declare the scalar variable "#xml".
Msg 156, Level 15, State 1, Line 417
Incorrect syntax near the keyword 'FOR'.
Msg 137, Level 15, State 1, Line 419
Must declare the scalar variable "#xml".
Msg 137, Level 15, State 2, Line 540
Must declare the scalar variable "#xml".
I also tried this:
SELECT #SQLStr = '<![CDATA[' + #tmpCode + N']]>';
it didn't help, either.
Error message that I got:
Msg 102, Level 15, State 1, Line 3
Incorrect syntax near '<'.
Msg 103, Level 15, State 4, Line 3
The identifier that starts with CDATA[DECLARE #xml xml SELECT TOP 1 #xml = x FROM iksemel ORDER BY id INSERT INTO ARTYKUL_TEST(ID_ARTYKULU,ID_MAGAZYNU' is too long. Maximum length is 128.
Msg 105, Level 15, State 1, Line 541
Unclosed quotation mark after the character string ')'.
Please help
Could you provide an example of the xml you're trying to generate? Based on the code you posted, I'm assuming it looks something like this.
<root>
<Instructors>
<row>
<InstructorName>Graff</InstructorName>
</row>
</Instructors>
<Instructors_TEST>
<row>0</row>
</Instructors_TEST>
</root>
You'll need to modify your generated SQL to be more like this:
SELECT (
SELECT * FROM Instructors FOR XML PATH('row'), TYPE
) AS Instructors,
(
SELECT 0 FROM Instructors FOR XML PATH('row'), TYPE
) AS Instructors_TEST
FOR XML PATH(''), ROOT('root')
The problem is not with the value (query) you're trying to store in the xml. Do a SELECT on the #tmpCode, paste it into the editor, and check whether its a valid string. It's not.
In your code, you'd get this:
SELECT #tmpCode = '''SELECT value(''ID_ARTYKULU[1]'')'''
--'SELECT value('ID_ARTYKULU[1]')'
But you want to use this:
SELECT #tmpCode = '''SELECT value(''''ID_ARTYKULU[1]'''')'''
--'SELECT value(''ID_ARTYKULU[1]'')'
A ghetto fix would be to replace your #tmpCode section with this:
SELECT #tmpCode = N'''' + REPLACE('SELECT value(''ID_ARTYKULU[1]'')', N'''', N'''''') + N''''
Since you're using dynamic SQL, you need to be very careful when escaping quotes.

Dynamically adding column to the temptable?

In my sqluery, i am trying to add columns dynamically, but it is showing error Like:
Msg 214, Level 16, State 2, Procedure sp_executesql, Line 1
Procedure expects parameter '#statement' of type 'ntext/nchar/nvarchar'.
this is my proc
declare #curntyear int
declare #pasyear int
declare #sql nvarchar(max)
declare #temp varchar(50)
select #pasyear=YEAR( DATEADD (YEAR,-3,GETDATE ()))
select #curntyear =YEAR (getdate())
print #pasyear
print #curntyear
create table #TempTable (years varchar(30))
insert into #TempTable select (cargo+port+railway+estate)as 'sum' from operatingincome where YEAR(createddate)=#pasyear
while (#curntyear >=#pasyear )
begin
set #pasyear =#pasyear +1
--select #temp=(cargo+port+railway+estate)as 'sum' from operatingincome where YEAR(createddate)=#pasyear
select #temp= convert(varchar,(cargo+port+railway+estate),106) from operatingincome where YEAR(createddate)= #pasyear
set #sql ='alter table #TempTable add '+ CONVERT(varchar,#pasyear,106)+' varchar(50)'
exec sp_executesql #sql
print #sql
set #sql = 'update #TempTable set '+CONVERT(varchar,#pasyear,106) +'='+#temp +' where years='''+CONVERT(varchar,#pasyear,106)+''
exec sp_executesql #sql
set #temp =''
end
select * from #TempTable
i am getting error like this :
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near '2009'.
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near '2010'.
alter table #TempTable add 2010 varchar(50)
update #TempTable set 2010=9300 where years=2010
Sounds like you're calling sp_executesql with a VARCHAR statement, when it needs to be NVARCHAR.
e.g. This will give the error because #SQL needs to be NVARCHAR
Declare your variable #sql varchar to nvarchar, that will work fine:
declare #sql nvarchar(max)
UPdate:
Change your sql setting as below: you need to use [] in column name as [ColumName]
set #sql ='alter table #TempTable add ['+ CONVERT(varchar,#pasyear,106)+'] varchar(50)'
set #sql = 'update #TempTable set ['+CONVERT(varchar,#pasyear,106) +']='+#temp +' where years='''+CONVERT(varchar,#pasyear,106)+''
Change
declare #sql varchar(max)
to be
declare #sql nvarchar(max)
You are told this in the error message and on MSDN (my bold)
[ #statement= ] statement
Is a Unicode string that contains a Transact-SQL statement or batch. statement must be either a Unicode constant or a Unicode variable.

Resources