Invalid STRING_SPLIT args in SQL Server - arrays

I am trying to parse a cell that is data type nvarchar(max) like it is csv in SQL Server 2017. I was hoping to use the STRING_SPLIT return a row of data for each value in the array-like string. However, when I run the following code I get an error.
select this_column
into #t
from that_table
where coordinate_x = 1
and coordinate_y = 7
select * from STRING_SPLIT(#t.this_column, ',')
Msg 4104, Level 16, State 1, Line 16
The multi-part identifier "#t.this_column" could not be bound
Msg 8116, Level 16, State 1, Line 16
Argument data type void type is invalid for argument 1 of string_split function
How can I parse this data?

You can't pass a table to a inline table function, you need to include it in your FROM:
SELECT {YourColumns}
FROM #t T
CROSS APPLY STRING_SPLIT(T.this_column, ',') SS;

You'll want to use a cross apply with your temp table
Here's a working example so you can see how that works:
DECLARE #TestData TABLE
(
[TestData] NVARCHAR(MAX)
);
INSERT INTO #TestData (
[TestData]
)
VALUES ( N'1,2,3,4,5,6,7,8,9');
SELECT [b].[value] FROM #TestData [a]
CROSS APPLY[STRING_SPLIT([a].[TestData], ',') [b];
So for your situation, just a small tweak to what you already have, something like:
SELECT [b].[value] FROM #t a
CROSS APPLY STRING_SPLIT(a.this_column,',') b

Related

SQL Server- How to use data in column for DATEADD - datepart

I want to pass data from a variable/ from table column as the 'datepart' when using DATEADD function. Below is snippet of my code where I'm seeing the error as below.
DECLARE #vchstring VARCHAR(20)
SET #vchstring='month'
SELECT DATEADD(#vchstring,1,GETDATE())
I get this error:
Msg 1023, Level 15, State 1, Line 104
Invalid parameter 1 specified for dateadd.
This could be a duplicate, but am not able to find any information.
SQL Server does not support macro substitution. You would either have to use Dynamic SQL or a nested case/IF or even a SELECT
Example
DECLARE #vchstring VARCHAR(20)
SET #vchstring='month'
Select Value
From ( values ('year' ,DATEADD(YEAR ,1,GETDATE()) )
,('month' ,DATEADD(MONTH ,1,GETDATE()) )
,('day' ,DATEADD(DAY ,1,GETDATE()) )
,('hour' ,DATEADD(HOUR ,1,GETDATE()) )
,('minute',DATEADD(MINUTE ,1,GETDATE()) )
) A (inc,value)
Where inc = #vchstring
Returns
Value
2020-06-05 10:09:29.660

Is it possible to have a view in sql-server 2008 that splits one row into many?

The back story is I am trying to write a view that takes a table who's every row is an ID and serialized data for that ID in a clob and presents it in sql navigable form. basically my code looks like:
CREATE VIEW UNSERIALIZED_TABLE_VIEW AS
SELECT
SOURCE_TABLE.ID SOURCE_ID,
a.*
FROM
SOURCE_TABLE,
FUNCTION_WHICH_UNSERIALIZES((SELECT DATA FROM SOURCE_TABLE WHERE ID = SOURCE_ID)
I tried putting the function in the select statement, but that just gave a syntax error about it being undefined. When it runs the error is usually about a subquery returning too many values. I could just unserialize the data in batches, but now I'm really curious what's going wrong.
Example Data
#0History:23:ALPHANUMERICSTUFF1234567ID:11:ACCT1234567SourceMode:6:ANNUAL.ModeChanges:UniqueIndex:23:ALPHANUMERICSTUFF1234567ID:11:ACCT1234567OldValue:1:+NewValue:6:ANNUALChangeType:1:AChangeDate:20:6/03/2013 2:49:32 AM.
#0History:UniqueIndex:95:NOTTHESAME0987654|ALPHANUMERIC534|PRETEND349235|95CHARACTERSID:47:GNR44718500|PNR48CDQ704|PGP48090798|FGDS2345236SourceMode:26:ANNUAL|C-P-D|ANNUAL|ANNUALLoan:3:|||ModeChanges:UniqueIndex:95:00487SOMETHING4264500ORD|992581PROBABLY04ORD|0048SHOULD238BET|0095CHARS436PR638FGP07VDCID:47:GNR44718500|PNR48CDQ704|PGP48090798|FGDS2345236OldValue:7:+|+|+|+NewValue:26:ANNUAL|C-P-D|ANNUAL|ANNUALChangeType:7:A|A|A|AChangeDate:91:12/22/2013 11:53:11 PM|4/22/2013 11:53:11 PM|12/22/2013 11:53:11 PM|12/22/2013 11:53:11 PM.
The data is serialized table data of the form COLUMN_NAME:LENGTH_OF_ENTRY:DATA_FOR_COLUMN_ROW_1|DATA_FOR_COLUMN_ROW2|....NEXT_COLUMN_NAME...
Example of Function:
CREATE FUNCTION FUNCTION_THAT_UNSERIALIZES (#clob varchar(max),#colname varchar(max)) RETURNS #NewValue TABLE (ID INT,value varchar(max)) AS
BEGIN
DECLARE #colstart INT,#lenstart INT,#lenend INT,#collen VARCHAR(MAX),#lngth INT,#tmp VARCHAR(MAX), #rowid INT,#value VARCHAR(max),#next INT;
SELECT
#colstart = CHARINDEX(#colname,#tmp)+1,
#lenstart = CHARINDEX(':',#tmp,#colstart)+1,
#lenend = CHARINDEX(':',#tmp,#lenstart),
#collen = SUBSTRING(#tmp,#lenstart,#lenend - #lenstart),
#lngth = CAST (#collen AS INT),
#tmp = SUBSTRING(#tmp,#lenend,#lngth);
WHILE LEN(#tmp) > 0 BEGIN
SET #next = CHARINDEX('|',#tmp);
IF #next > 0 BEGIN
SET #value = SUBSTRING(#tmp,0,#next);
SET #tmp = SUBSTRING(#tmp,#next+1,LEN(#tmp) - #next);
END ELSE BEGIN
SET #value = #tmp;
SET #tmp = '';
END
INSERT INTO #NewValue VALUES(#rowid,#value)
SET #rowid = #rowid+1;
END
RETURN
Example Error
Msg 512, Level 16, State 1, Line 7
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
Msg 4104, Level 16, State 1, Line 15
The multi-part identifier "SOURCE_TABLE.SOURCE_ID" could not be bound.
.. I think there might have been another one, but can't figure out how to reproduce it right this minute.
I think this might be the syntax you need to accomplish what I think you are trying to do.
CREATE VIEW UNSERIALIZED_TABLE_VIEW AS
SELECT
SOURCE_TABLE.ID SOURCE_ID,
a.*
FROM SOURCE_TABLE
CROSS APPLY FUNCTION_WHICH_UNSERIALIZES(DATA, #colname) a
I'm not certain what your #colname parameter should be; it is left out of your code in the question.

Invalid object name error for a function used in sql server

I am using sql-server 2012:
drop table ttt
create table ttt(id int,amt int)
insert into ttt values(1,100),(2,200),(1,200),(3,400),(1,500)
create function dbo.t1(#id int)
returns int
with returns null on null input
as
begin
declare #amt_total int
select #amt_total=sum(amt) from ttt
where id=#id
return #amt_total
end
select t.id,t.amt,f.id from ttt t cross apply dbo.t1(t.id) f
The code returns following error on execution:
Msg 208, Level 16, State 3, Line 16
Invalid object name 'dbo.t1'.
any help?
the function,tables are all present in same schema
The syntax you are using is suitable for table-valued user-defined functions which return a table data type instead of just a scalar value.
Try this syntax instead:
SELECT t.id, t.amt, f.id
FROM ttt t
CROSS APPLY (SELECT dbo.t1(t.id) ) f(id)
its a scalar function. you need to call it like this
select t.id,t.amt,dbo.t1(t.id) id from ttt t
For more info about types of functions in SQL Server, refer here

SQL SERVER FOR XML EXPLICIT

I want to assign the result of a SELECT FOR XML EXPLICIT statement to a XML Variable such as
CREATE PROCEDURE BILLING_RESPONSE
AS DECLARE #Data AS XML
SET #Data = (SELECT
1 AS Tag,
NULL AS Parent,
NULL AS 'CallTransactions!1!',
NULL AS 'TCALTRS!2!TRS_DAT_TE!cdata',
NULL AS 'TCALTRS!2!TRS_CRT_DT!Element'
UNION ALL
SELECT
2 AS Tag,
1 AS Parent,
NULL,
TRS_DAT_TE,
TRS_CRT_DT
FROM TCALTRS
WHERE TRS_CRT_DT between CONVERT(date,GETDATE()-1) and CONVERT(date,getdate()) and
TRS_DAT_TE like '%(Submit Response)%'
FOR XML EXPLICIT
)
SELECT #DATA
GO
When i execute this query am getting the following error
Msg 1086, Level 15, State 1, Procedure BILLING_RESPONSE, Line 22
The FOR XML clause is invalid in views, inline functions, derived tables, and subqueries when they contain a set operator. To work around, wrap the SELECT containing a set operator using derived table syntax and apply FOR XML on top of it.
If this is it, you don't need the #Data variable. Let your sp return the result of query directly and you're done.
CREATE PROCEDURE BILLING_RESPONSE AS
SELECT
1 AS Tag,
NULL AS Parent,
NULL AS 'CallTransactions!1!',
NULL AS 'TCALTRS!2!TRS_DAT_TE!cdata',
NULL AS 'TCALTRS!2!TRS_CRT_DT!Element'
UNION ALL
SELECT
2 AS Tag,
1 AS Parent,
NULL,
TRS_DAT_TE,
TRS_CRT_DT
FROM TCALTRS
WHERE TRS_CRT_DT between CONVERT(date,GETDATE()-1) and CONVERT(date,getdate()) and
TRS_DAT_TE like '%(Submit Response)%'
FOR XML EXPLICIT
The error is not particularly clear, but what it is saying is that you can't use the FOR XML clause in the inline subquery because it contains a UNION (a type of set operator)
The suggested workaround is to wrap the subquery in something else and call it separately, for example:
CREATE PROCEDURE BILLING_RESPONSE
AS DECLARE #Data AS XML
;WITH DATA AS(
SELECT
1 AS Tag,
NULL AS Parent,
NULL AS 'CallTransactions!1!',
NULL AS 'TCALTRS!2!TRS_DAT_TE!cdata',
NULL AS 'TCALTRS!2!TRS_CRT_DT!Element'
UNION ALL
SELECT
2 AS Tag,
1 AS Parent,
NULL,
TRS_DAT_TE,
TRS_CRT_DT
FROM TCALTRS
WHERE TRS_CRT_DT between CONVERT(date,GETDATE()-1) and CONVERT(date,getdate()) and
TRS_DAT_TE like '%(Submit Response)%'
FOR XML EXPLICIT
)
SELECT #Data = (SELECT * FROM DATA FOR XML EXPLICIT)
SELECT #DATA
GO

SQL Server append query

I have the following (not working) query:
insert into [MyDB].[dbo].[Reports_StepsStat]
(ActivityID,TaskID,StepIndex,StepStatus,TimeSpanInSeconds,Score)
VALUES (
SELECT
tasks.ActivityID as ActivityID,
tasks.ID as TaskID,
[StepIndex]=item.value('(StepIndex)[1]', 'NVARCHAR(MAX)'),
[StepStatus]=item.value('(Status)[1]', 'NVARCHAR(MAX)'),
[TimeSpanInSeconds] = DATEDIFF(MINUTE, item.value('(StartedOn)[1]', 'datetime'),item.value('(FinishedOn)[1]', 'datetime')),
tasks.Score as Score
FROM
[MyDB].[dbo].[Tasks] as tasks
CROSS APPLY
[Progress].nodes ('//Progress/Steps/ProgressStep') Progress(item)
)
The inner select query (SELECT task.ActivityID..) works perfectly and produces the expected table.
The outer insert into part is supposed to append the result of the inner part to a table by the name of Reports_StepsStat. This does not work.
I have tried and succeeded doing that with SELECT INTO, but apparently SELECT INTO can only be used to create a new table, and not to append to an existing table, which is what I need.
The errors I get are:
Msg 156, Level 15, State 1, Line 6
Incorrect syntax near the keyword 'SELECT'.
Msg 102, Level 15, State 1, Line 14
Incorrect syntax near ')'.
I think VALUES ( is not required in your query.
insert into [MyDB].[dbo].[Reports_StepsStat]
(ActivityID,TaskID,StepIndex,StepStatus,TimeSpanInSeconds,Score)
SELECT
tasks.ActivityID as ActivityID,
tasks.ID as TaskID,
[StepIndex]=item.value('(StepIndex)[1]', 'NVARCHAR(MAX)'),
[StepStatus]=item.value('(Status)[1]', 'NVARCHAR(MAX)'),
[TimeSpanInSeconds]=DATEDIFF(MINUTE,item.value('(StartedOn)[1]', 'datetime'),
item.value('(FinishedOn)[1]', 'datetime')),
tasks.Score as Score
FROM [MyDB].[dbo].[Tasks] as tasks
CROSS APPLY [Progress].nodes ('//Progress/Steps/ProgressStep') Progress(item)
Syntax is
insert into a select * from b
so just omit the values (...) surroundng the select...

Resources