Converting the nvarchar to int - sql-server-2008

I have google online this question and for the life of me couldn't figure out why this kept throwing errors, any help is appreciated.
Conversion failed when converting the nvarchar value 'SELECT #orderid
= t.orderid FROM (SELECT *, ROW_NUMBER() OVER (PARTITION BY id ORDER BY creationdatetime DESC) AS row FROM
[intranet].[dbo].handbook_appendix_data WHERE id = ' to data type int.
DECLARE #sql nvarchar(500)
DECLARE #table varchar(40)
SET #table = 'handbook_section_data';
SET #table = 'handbook_appendix_data';
DECLARE #parentid INT
DECLARE #id INT
DECLARE #published INT
DECLARE #orderid INT
SET #parentid = 2
SET #id = -1
SET #published = 1
SET #sql = N'SELECT #orderid = t.orderid FROM
(SELECT *, ROW_NUMBER() OVER (PARTITION BY id ORDER BY creationdatetime DESC) AS row FROM [intranet].[dbo].'+#table+' WHERE id = '+#id+' AND published = '+#published+') AS t
WHERE t.published = '+#published+' AND t.row = 1';
EXEC SP_EXECUTESQL #sql, N'#orderid INT OUTPUT', #orderid = #orderid OUTPUT --Get the OrderID from ID
PRINT #orderid

You need to convert your #id and #published ints to a varchar
convert(varchar(50),#published)
ie
SET #sql = N'SELECT #orderid = t.orderid FROM
(SELECT *, ROW_NUMBER() OVER (PARTITION BY id ORDER BY creationdatetime DESC) AS row FROM [intranet].[dbo].'+#table+' WHERE id = '+ convert(varchar(50),#id) +' AND published = '+ convert(varchar(50),#published) +') AS t
WHERE t.published = '+convert(varchar(50), #published) +' AND t.row = 1';
A better solution would be to avoid the string concatenation, and pass the #id and #published parameters using the sp_executesql as you are already doing with #orderid, or to question the requirement for dynamic SQL at all?

You need to cast the integer variables to a character type:
....
WHERE id =' + cast(#id as varchar(32)) + ' AND published = ' + cast(#published as varchar(32)) + ') AS t ...

WHERE t.published = '+#published+' AND t.row = 1'
#published is an int. SQL Server has decided that + must be between two ints, and is trying to convert the string to an int.
To stop this, force #published to be a string instead - then it's adding two strings (concatenation) instead:
WHERE t.published = '+CONVERT(varchar(10),#published)+' AND t.row = 1'

Related

Query run as stored procedure (sp_sqlexec) delivers no results (T-SQL, SQL Server)

I want to run a query that shows me all columns from all tables in a database with the datatype varchar and a maximum length of 8000 characters.
This is my code so far.
DECLARE #tabs VARCHAR(MAX);
SET #tabs =
(
SELECT STUFF(( SELECT DISTINCT ',' + [TABLE_NAME]
FROM [DB-Test].INFORMATION_SCHEMA.COLUMNS
WHERE DATA_TYPE = 'VARCHAR' AND
CHARACTER_MAXIMUM_LENGTH = 8000
FOR XML PATH('')), 1, 1, '')
);
DECLARE #cols VARCHAR(MAX)
SET #cols =
(
SELECT STUFF(( SELECT DISTINCT ',' + [TABLE_NAME] + '.' + [COLUMN_NAME]
FROM [DB-Test].INFORMATION_SCHEMA.COLUMNS
WHERE DATA_TYPE = 'VARCHAR' AND
CHARACTER_MAXIMUM_LENGTH = 8000
FOR XML PATH('')), 1, 1, '')
);
DECLARE #query VARCHAR(MAX) = 'SELECT ' + #cols + ' FROM ' + #tabs
EXEC sp_sqlexec #query
When I run the query I get all the column names, but not the values in the columns. It's empty. No 'NULL'-values. As if #cols is interpreted as simple string maybe.
Why?
(When I read out #cols and #tabs they are correct.)
I guess there is one table available in your database which have column with VARCHAR datatype and 8000 length but that table don't have any records. Try by including only those column and table which have at least one record available.
You can try below. Check it and let me know if it works.
DECLARE #tabs VARCHAR(MAX) = ''
; WITH CTE AS
(
SELECT DISTINCT TA.NAME TABLENAME
, SUM(PA.ROWS) OVER (PARTITION BY TA.NAME ) NOOFROW
FROM SYS.TABLES TA
INNER JOIN SYS.PARTITIONS PA ON PA.OBJECT_ID = TA.OBJECT_ID
INNER JOIN SYS.SCHEMAS SC ON TA.SCHEMA_ID = SC.SCHEMA_ID
WHERE TA.IS_MS_SHIPPED = 0 AND PA.INDEX_ID IN (1,0)
), TABLENAME AS
(
SELECT ITBL.[TABLE_NAME]
FROM INFORMATION_SCHEMA.COLUMNS ITBL
WHERE ITBL.DATA_TYPE = 'VARCHAR' AND
ITBL.CHARACTER_MAXIMUM_LENGTH = 8000
AND EXISTS(SELECT 1 FROM CTE WHERE CTE.TABLENAME = ITBL.TABLE_NAME AND CTE.NOOFROW > 0) -- To check no of record available in table
)
SELECT #tabs = #tabs+ISNULL(','+TABLE_NAME, '')
FROM TABLENAME
DECLARE #cols VARCHAR(MAX) = '';
; WITH CTE AS
(
SELECT DISTINCT TA.NAME TABLENAME
, SUM(PA.ROWS) OVER (PARTITION BY TA.NAME ) NOOFROW
FROM SYS.TABLES TA
INNER JOIN SYS.PARTITIONS PA ON PA.OBJECT_ID = TA.OBJECT_ID
INNER JOIN SYS.SCHEMAS SC ON TA.SCHEMA_ID = SC.SCHEMA_ID
WHERE TA.IS_MS_SHIPPED = 0 AND PA.INDEX_ID IN (1,0)
), TABLENAME AS
(
SELECT ITBL.[TABLE_NAME], ITBL.[COLUMN_NAME]
FROM INFORMATION_SCHEMA.COLUMNS ITBL
WHERE ITBL.DATA_TYPE = 'VARCHAR' AND
ITBL.CHARACTER_MAXIMUM_LENGTH = 8000
AND EXISTS(SELECT 1 FROM CTE WHERE CTE.TABLENAME = ITBL.TABLE_NAME AND CTE.NOOFROW > 0) -- To check no of record available in table
)
SELECT #cols = #cols+ISNULL(','+[TABLE_NAME]+'.'+[COLUMN_NAME], '')
FROM TABLENAME
IF LEN(#cols) > 0 AND LEN(#tabs) > 0
BEGIN
DECLARE #query VARCHAR(MAX) = 'SELECT ' + STUFF(#cols,1,1,'') + ' FROM ' + STUFF(#tabs,1,1, '')
EXEC sp_sqlexec #query
END
ELSE
BEGIN
PRINT 'No Column available with data where it''s datatype is VARCHAR and length is 8000'
END

single column to rows in sqlserver

I want to split the two columns into two rows in a single table separated by ‘;’ in Sql Server 2008. Please help me to resolve to solve this.
Columns like:
1;2;3;4;5;6;7; and a;b;c;d;e;f;g;
Output Rows like:
1 a
2 b
3 c
4 d
5 e
6 f
7 g
First you are going to need a split function as such :
CREATE function [dbo].[Split]
(
#string nvarchar(max),
#delimiter nvarchar(20)
)
returns #table table
(
[Value] nvarchar(max)
)
begin
declare #nextString nvarchar(max)
declare #pos int, #nextPos int
set #nextString = ''
set #string = #string + #delimiter
set #pos = charindex(#delimiter, #string)
set #nextPos = 1
while (#pos <> 0)
begin
set #nextString = substring(#string, 1, #pos - 1)
insert into #table
(
[Value]
)
values
(
#nextString
)
set #string = substring(#string, #pos + len(#delimiter), len(#string))
set #nextPos = #pos
set #pos = charindex(#delimiter, #string)
end
return
end
Then using this code :
SELECT col1.Value as val1,
col2.Value as val2
FROM
(SELECT Value,
ROW_NUMBER() over(order by value asc) as rownum
FROM (
VALUES('1;2;3;4;5;6;7')
) valued(X) CROSS APPLY
DBO.SPLIT(X,';') AS SPLITEDCOL ) as col1 INNER JOIN
(SELECT Value,
ROW_NUMBER() over(order by value asc) as rownum
FROM (
VALUES('A;B;C;D;E;F;G')
) valued1(X) CROSS APPLY
DBO.SPLIT(X,';') AS SPLITEDCOL ) as col2
ON COL1.rownum = col2.rownum
if your two columns are from a table you can select them as such :
SELECT Value,
ROW_NUMBER() over(order by value asc) as rownum
FROM YourTable CROSS APPLY
DBO.SPLIT(YourColumnName,';') AS SPLITEDCOL
Note that 1 subset using cross apply is necessary for each column you want to return in rows
Hope this helps
Declare #ID as Varchar(1000)
set #ID = '1;2;3;4;5;6;7;'
SELECT
LTRIM(RTRIM(m.n.value('.[1]','varchar(8000)'))) AS ID
FROM
(
SELECT CAST('<XMLRoot><RowData>' + REPLACE(#ID,';','</RowData><RowData>') + '</RowData></XMLRoot>' AS XML) AS x
)t
CROSS APPLY x.nodes('/XMLRoot/RowData')m(n)
DECLARE #Table1 TABLE(ID INT, Value char)
INSERT INTO #Table1 VALUES (1,'a'),(1,'b'),(1,'c'),(1,'d')
SELECT STUFF((SELECT '; ' + CAST(ID AS VARCHAR(10)) [text()]
FROM #Table1
WHERE ID = t.ID
FOR XML PATH(''), TYPE)
.value('.','NVARCHAR(MAX)'),1,2,' ') ID
,STUFF((SELECT '; ' + CAST(Value AS VARCHAR(10)) [text()]
FROM #Table1
WHERE ID = t.ID
FOR XML PATH(''), TYPE)
.value('.','NVARCHAR(MAX)'),1,2,' ') value
FROM #Table1 t

Must declare the scalar varialble

I am using this simple code to pivot some column.
But I can't make it work due to that error.
DECLARE #IO_dy AS VARCHAR(100) = '>9C604-M'
DECLARE #style_dy AS VARCHAR (100) = 'S1415MBS06'
DECLARE #query AS VARCHAR(8000)
DECLARE #con AS VARCHAR(8000)
SET #con = STUFF((SELECT distinct ',' + QUOTENAME(Size_id)
FROM iPLEXSTY_SIQ
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SET #query = 'SELECT *
FROM (
SELECT DISTINCT a.Po_no,a.Article_id,a.Season_id,a.Customer_id,a.Destn_id,b.planned_dt, (c.Description + c.Resource_id) AS comb_size,a.Qty,a.Size_id
from iPLEXSTY_SIQ a
INNER JOIN iPLEX_BULK_PO_DET b on b.upload_batch_id = a.Batch_id
INNER JOIN iPLEXCOLORS c on c.Seq_no = a.Seq_no
WHERE IO_no = #IO_dy AND Style_id = #style_dy //ERROR HERE
GROUP BY a.Po_no,a.Article_id,a.Season_id,a.Customer_id,a.Destn_id,b.planned_dt,(c.Description + c.Resource_id),a.Qty,A.Size_id
) as s
PIVOT
(
SUM(Qty)
FOR Size_id IN (' +#con+ ')
)AS pvt'
EXEC(#query)
addition to another answer
just single quotes to the variable names used in the query
DECLARE #IO_dy AS VARCHAR(100) = '>9C604-M'
DECLARE #style_dy AS VARCHAR (100) = 'S1415MBS06'
DECLARE #query AS VARCHAR(8000)
DECLARE #con AS VARCHAR(8000)
SET #con = STUFF((SELECT distinct ',' + QUOTENAME(Size_id)
FROM iPLEXSTY_SIQ
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SET #query = 'SELECT *
FROM (
SELECT DISTINCT a.Po_no,a.Article_id,a.Season_id,a.Customer_id,a.Destn_id,b.planned_dt, (c.Description + c.Resource_id) AS comb_size,a.Qty,a.Size_id
from iPLEXSTY_SIQ a
INNER JOIN iPLEX_BULK_PO_DET b on b.upload_batch_id = a.Batch_id
INNER JOIN iPLEXCOLORS c on c.Seq_no = a.Seq_no
WHERE IO_no = '''+#IO_dy+''' AND Style_id = '''+#style_dy+''' //ERROR HERE
GROUP BY a.Po_no,a.Article_id,a.Season_id,a.Customer_id,a.Destn_id,b.planned_dt,(c.Description + c.Resource_id),a.Qty,A.Size_id
) as s
PIVOT
(
SUM(Qty)
FOR Size_id IN (' +#con+ ')
)AS pvt'
EXEC(#query)
and also as another answer explains to set values to varchar using default keyword
You can't declare and initialize value of variable using "=". So instead of:
DECLARE #IO_dy AS VARCHAR(100) = '>9C604-M'
Use
DECLARE #IO_dy AS VARCHAR(100) DEFAULT '>9C604-M'
^^^^^^^
See this for syntax

Convert one row of data in sql server to columns

I have a query that outputs just one row of data. I want to convert that row to column and the column to row.
My original query
------------------------
ID Name Desc
------------------------
1 Nisha Some desc
what I need
--------------------------
FieldName FieldValue
--------------------------
ID 1
Name Nisha
Description Some Desc
declare #colNum int, #i int = 1, #a nvarchar(4000)
select #colNum=count(COLUMN_NAME) from INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'YourTable'
set #a = '
declare #tempTable table
(
slno int
,field nvarchar(100)
,value nvarchar(100)
)
insert into #tempTable (slno,field)
select ROW_NUMBER() over (order by ordinal_position asc),COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = ''YourTable''
declare #p nvarchar(100)
'
declare #colname nvarchar(100)
while #i<=#colNum
begin
select #colname =a.COLUMN_NAME from (select COLUMN_NAME,ORDINAL_POSITION
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'YourTable'
)as a
where a.ORDINAL_POSITION = #i
set #a = #a + '
select #p='+#colname+' from YourTable
update #tempTable set
value = #p
where slno = '+CONVERT(nvarchar(5), #i)
+'
'
set #i=#i+1
end
set #a = #a + ' select * from #tempTable'
declare #tempTable table
(
slno int
,field nvarchar(100)
,value nvarchar(100)
)
insert into #tempTable exec (#a)
select * from YourTable
select * from #tempTable

What can I use instead of #Temp table in sql function

Here is my sql query.
CREATE FUNCTION UF_GetOrderProducts
(
#OrderId int
)
RETURNS VARCHAR(500)
AS
BEGIN
SELECT Identity(int,1,1) ID, ProductId INTO #Temp FROM OrderProduct WHERE OrderId = #OrderId
Declare #Id int,
#Count int,
#LoopCount int,
#ProductList VARCHAR(500),
#ProductListTemp VARCHAR(500)
SET #Count = (Select Count(*) From #Temp)
SET #LoopCount = 1
SET #ProductList = ''
WHILE #LoopCount <= #Count
BEGIN
SET #ProductListTemp =( SELECT Name FROM Product WHERE ProductId =(Select ProductId from #Temp Where ID = #LoopCount))
SET #ProductList +=#ProductListTemp + '<br/>'
Set #LoopCount=#LoopCount + 1
END
DROP TABLE #Temp
RETURN #ProductList
END
GO
I have to loop in #Temp Table. Do you have any other suggestions?
Instead of temp table you can use a table variable.
declare #Temp TABLE (ID int identity, ProductId int)
insert into #Temp(ProductId)
select ProductId
from OrderProduct
where OrderId = #OrderId
But you could rewrite your function without a loop.
Something like this should do what you want.
create function IF_GetOrderProducts
(
#OrderId int
)
returns varchar(500)
as
begin
return
(
select Name+'<br/>'
from Product as P
inner join OrderProduct as OP
on P.ProductId = OP.ProductId
where OP.OrderId = #OrderId
for xml path(''), type
).value('.', 'varchar(500)')
end