Handling variables in SQL Server - sql

I have a procedure that needs to handle up to 60 different variables.
The variables have a standardized naming convention.
#TextParameter1 varchar(443) = NULL,
#TextParameter2 varchar(443) = NULL,
#TextParameter3 varchar(443) = NULL
I need to be able to check which variables are NULL and which aren't, and then handle the values of the non-null variables.
I tried using dynamic SQL to iterate over the variables by making the first portion of the variable name a string and iterating through the numbers on the end.
declare #rownum int = 1
while #rownum <= 60
declare #var_sql nvarchar(max) = 'INSERT INTO #slicer
SELECT IDENTITY(Int, 1, 1) AS rowkey, value
FROM STRING_SPLIT(CAST(#DetailQueryTextParameter' + CAST(#rownum AS nvarchar(3)) AS varchar(4000)), '^')'
execute #var_sql
Set #rownum = #rownum + 1
This will return an error claiming that #DetailQueryTextParameter needs to be declared first. What is the best way to handle all of these variables? I could do by writing a line of code for every single variable, but it seems like there is a better way. Can I insert the variable names into a table and iterate from there?

(The below was updated to include the SPLIT_STRING().)
You can use a VALUES subselect (not sure if that is the proper term) to combine all of your parameters into a single collection. You can then filter out the null values and pass the remaining values into STRING_SPLIT() using a CROSS APPLY.
DECLARE
#TextParameter1 varchar(443) = NULL,
#TextParameter2 varchar(443) = 'aaa^bbb',
#TextParameter3 varchar(443) = NULL,
#TextParameter4 varchar(443) = 'xxx^yyy^zzz',
#TextParameter5 varchar(443) = NULL
SELECT A.*, B.Value AS SplitValue
FROM (
VALUES
(1, #TextParameter1),
(2, #TextParameter2),
(3, #TextParameter3),
(4, #TextParameter4),
(5, #TextParameter5)
) A(Parameter, Value)
CROSS APPLY STRING_SPLIT(A.Value, '^') B
WHERE A.Value IS NOT NULL
Which would yield results like:
Parameter
Value
SplitValue
2
aaa^bbb
aaa
2
aaa^bbb
bbb
4
xxx^yyy^zzz
xxx
4
xxx^yyy^zzz
yyy
4
xxx^yyy^zzz
zzz
See this db<>fiddle.

Related

Scalar variable issue not being able to use in Select Query SQL Server

I 'm not able to use both Declare statements in my select query when I do the insert into.
How do you use a column itemId to be set in a another column called id?
How do you write a same string to a specific column?
Why can't I call my scalar variable ?
DECLARE #Solutions_id as INT
DECLARE #Solutions_name as nvarchar(50)
INSERT INTO ticket_historical_actions
(
[id]
,[type]
[Solutions _rowId]
,[Solutions_dw_dateCreate]
,[Solutions_dw_dateMod]
,[Solutions_dw_dateDelete]
,[Solutions_sourceId]
,[Solutions_date_create]
,[Solutions_date_mod]
,[Solutions_date_approval]
,[Solutions_itemId]
,[Solutions_solutionTypeName]
,[Solutions_content_plainText]
,[Solutions_userId]
,[Solutions_userId_editor]
,[Solutions_userId_approval]
,[Solutions_userName]
,[Solutions_userName_approval]
,[Solutions_status]
,[Ticket_rowId]
,[Ticket_dw_dateCreate]
,[Ticket_dw_dateMod]
,[Ticket_dw_dateDelete]
,[Ticket_sourceId]
,[Ticket_date_create]
,[Ticket_date_mod]
,[Ticket_date_close]
,[Ticket_date_solve]
,[Ticket_entityId]
,[Ticket_name]
,[Ticket_date]
,[Ticket_status]
,[Ticket_is_deleted]
,[Ticket_content_PlainText]
,[Ticket_type]
,[Ticket_urgency]
,[Ticket_impact]
,[Ticket_priority]
,[Ticket_requestTypeId]
,[Ticket_userId_lastUpdater]
,[Ticket_userId_recipient]
,[Ticket_time_to_resolve]
,[Ticket_time_to_own]
,[Users_rowId]
,[Users_dw_dateCreate]
,[Users_dw_dateMod]
,[Users_dw_dateDelete]
,[Users_sourceId]
,[Users_date_create]
,[Users_date_mod]
,[Users_name]
,[Users_LastName]
,[Users_firstName]
,[Users_phone]
,[Users_mobile]
,[Users_language]
,[Users_profileId]
,[Users_entitieId]
,[Users_titleId]
,[Users_categoryId]
,[Users_managerId]
,[Company_rowId]
, [Company_dw_dateCreate]
,[Company_dw_dateMod]
,[Company_dw_dateDelete]
,[Company_sourceId]
,[Company_date_mod]
,[Company_date_create]
,[Company_completename]
,[Company_name]
,[Company_address]
,[Company_postcode]
,[Company_town]
,[Company_state]
,[Company_country]
,[Company_phonenumber]
,[Company_email]
,[Company_admin_email]
,[Company_admin_name]
)
SELECT
#Solutions_id =[itemId], #Solutions_name = 'Solutions',
ts.[rowId]
,ts.[dw_dateCreate]
,ts.[dw_dateMod]
,ts.[dw_dateDelete]
,ts.[sourceId]
,ts.[date_create]
,ts.[date_mod]
,ts.[date_approval]
,ts.[itemId]
,ts.[solutionTypeName]
,ts.[content_plainText]
,ts.[userId]
,ts.[userId_editor]
,ts.[userId_approval]
,ts.[userName]
,ts.[userName_approval]
,ts.[status]
, tt. [rowId]
,tt.[dw_dateCreate]
,tt.[dw_dateMod]
,tt.[dw_dateDelete]
,tt.[sourceId]
,tt.[date_create]
,tt.[date_mod]
,tt.[date_close]
,tt.[date_solve]
,tt.[entityId]
,tt.[name]
,tt.[date]
,tt.[status]
,tt.[is_deleted]
,tt.[content_PlainText]
,tt.[type]
,tt.[urgency]
,tt.[impact]
,tt.[priority]
,tt.[requestTypeId]
,tt.[userId_lastUpdater]
,tt.[userId_recipient]
,tt.[time_to_resolve]
,tt.[time_to_own]
, tu.[rowId]
,tu.[dw_dateCreate]
,tu.[dw_dateMod]
,tu.[dw_dateDelete]
,tu.[sourceId]
,tu.[date_create]
,tu.[date_mod]
,tu.[name]
,tu.[LastName]
,tu.[firstName]
,tu.[phone]
,tu.[mobile]
,tu.[language]
,tu.[profileId]
,tu.[entitieId]
,tu.[titleId]
,tu.[categoryId]
,tu.[managerId]
, tc. [rowId]
,tc.[dw_dateCreate]
,tc.[dw_dateMod]
,tc.[dw_dateDelete]
,tc.[sourceId]
,tc.[date_mod]
,tc.[date_create]
,tc.[completename]
,tc.[name]
,tc.[address]
,tc.[postcode]
,tc.[town]
,tc.[state]
,tc.[country]
,tc.[phonenumber]
,tc.[email]
,tc.[admin_email]
,tc.[admin_name]
FROM
ticket_ticketSolutions ts
left join ticket_tickets tt
on ts.itemId =tt.sourceId
left join ticket_users tu
on ts.userId = tu.sourceId
left join ticket_company tc
on tu.entitieId = tc.sourceId
Would tell me if possible how to do it?
Thank you very much.
I'm just going to answer, even though I have stated this in the comments of both your questions.
The problem here is you are trying to assign a value to your variables in the same statement you are trying to return a dataset; in T-SQL that in not allowed.
In short, you have something like this:
SELECT #MyVariable = SomeColumn,
AnotherColumn
FROM dbo.YourTable
WHERE ID = 'SomeID';
So you want to return the value of AnotherColumn to the presentation layer, but assign the value of SomeColumn to the variable #MyVariable; you can't do this.
Instead, you have to use 2 statements:
SELECT #MyVariable = SomeColumn --Assigns the value to #MyVariable
FROM dbo.YourTable
WHERE ID = 'SomeID';
SELECT AnotherColumn --Returns the dataset to the presentation layer
FROM dbo.YourTable
WHERE ID = 'SomeID';

Find a string inside a string and update in SQL Server

I have a table like this :
create table Fbank (id int, COCODE nvarchar(max))
insert into Fbank
values (1, '<row xml:space="preserve" id="174580000041250.040002">
<c1>HTG115960001</c1>
<c2>14013514,48</c2>
<c3>222</c3>
<c4>BAL MIGRATED</c4>
<c5>NULL</c5>
<c6>NULL</c6>
<c7>NULL</c7>
<c8>9900</c8>
<c9>11596</c9>
<c10>20151017</c10>
<c11>HTG</c11>
<c12>NULL</c12>
<c13>NULL</c13>
<c14>FT1529010083</c14>
<c15>1</c15>
<c16>FT1529010083</c16>
<c17>FT</c17>
<c18>20151017</c18>
<c19>NULL</c19>
<c20>0</c20>
<c21>5033_INPUTTER__OFS_AUTO.FT</c21>
<c22>5033_INPUTTER_OFS_AUTO.FT</c22>
<c23>1510181127</c23>
<c24>HG0010001</c24>
</row>')
I need to replace the string inside the tag c24 tag..
Excepted output: I need to replace the letter 'G' to be replaced with 'T' like this inside c24 tag - HT0010001 and all the rest should be same unchanged...
What I tired:
declare #searchText varchar(20) = (
select SUBSTRING(COCODE,CHARINDEX('<c24>', COCODE), 7)
from FBNK_EB_SFF_ACCT_HI000)
update Fbank
set cocode = STUFF(#searchText, CHARINDEX('<c24>', COCODE), 1, 'T')
If the code always begins with 'H', then I imagine it's easier to just have '<c24>H' be part of the string to replace, but then add it back again:
update Fbank
set COCODE = replace(cocode, '<c24>HG', '<c24>HT');
If it doesn't, then I'd say you're on the right track with charindex and substring. But use patindex instead, and update fbank directly, don't put the search term into any variable. If you're trying to split up your logic into parts, consider cross apply:
update fb
set cocode = stuff(cocode, ix, 1, 'T')
from Fbank fb
cross apply (select ix = patindex('%<c24>%', cocode) + 6) ap
where substring(cocode, ix, 1) = 'G'

Error Handling for numbers of delimiters when extracting substrings

Situation: I have a column where each cell can have up to 5 delimiters. However, it's possible that there are none.
Objective: How do i handle errors such as :
Invalid length parameter passed to the LEFT or SUBSTRING function.
in the case that it cannot find the specified delimiter.
Query:
declare #text VARCHAR(111) = 'abc-def-geeee-ifjf-zzz'
declare #start1 as int
declare #start2 as int
declare #start3 as int
declare #start4 as int
declare #start_index_reverse as int
set #start1 = CHARINDEX('-',#text,1)
set #start2 = CHARINDEX('-',#text,charindex('-',#text,1)+1)
set #start3 = CHARINDEX('-',#text,charindex('-',#text,CHARINDEX('-',#text,1)+1)+1)
set #start4 = CHARINDEX('-',#text,charindex('-',#text,CHARINDEX('-',#text,CHARINDEX('-',#text,1)+1)+1)+1)
set #start_index_reverse = CHARINDEX('-',REVERSE(#text),1)
select
LEFT(#text,#start1-1) AS Frst,
SUBSTRING(#text,#start1+1,#start2-#start1-1) AS Scnd,
SUBSTRING(#text,#start2+1,#start3-#start2-1) AS Third,
SUBSTRING(#text,#start3+1,#start4-#start3-1)AS Third,
RIGHT(#text,#start_index_reverse-1) AS Lst
In this case my variable includes 5 delimiters and so my query works but if i removed one '-' it would break.
XML support in SQL Server brings about some unintentional but useful tricks. Converting this string to XML allows for some parsing that is far less messy than native string handling, which is very far from awesome.
DECLARE #test varchar(111) = 'abc-def-ghi-jkl-mnop'; -- try also with 'abc-def'
;WITH n(x) AS
(
SELECT CONVERT(xml, '<x>' + REPLACE(#test, '-', '</x><x>') + '</x>')
)
SELECT
Frst = x.value('/x[1]','varchar(111)'),
Scnd = x.value('/x[2]','varchar(111)'),
Thrd = x.value('/x[3]','varchar(111)'),
Frth = x.value('/x[4]','varchar(111)'),
Ffth = x.value('/x[5]','varchar(111)')
FROM n;
For a table it's almost identical:
DECLARE #foo TABLE ( col varchar(111) );
INSERT #foo(col) VALUES('abc-def-ghi-jkl-mnop'),('abc'),('def-ghi');
;WITH n(x) AS
(
SELECT CONVERT(xml, '<x>' + REPLACE(col, '-', '</x><x>') + '</x>')
FROM #foo
)
SELECT
Frst = x.value('/x[1]','varchar(111)'),
Scnd = x.value('/x[2]','varchar(111)'),
Thrd = x.value('/x[3]','varchar(111)'),
Frth = x.value('/x[4]','varchar(111)'),
Ffth = x.value('/x[5]','varchar(111)')
FROM n;
Results (sorry about the massive size, seems this doesn't handle 144dpi well):
add a test before your last select
then you should decide how to handle the other case (when one of start is 0)
You can also refer to this link about splitting a string in sql server
which is uses a loop and can handle any number of delimiters
if #start1>0 and #start2>0 and #start3>0 and #start4>0
select LEFT(#text,#start1-1) AS Frst,
SUBSTRING(#text,#start1+1,#start2-#start1-1) AS Scnd,
SUBSTRING(#text,#start2+1,#start3-#start2-1) AS Third,
SUBSTRING(#text,#start3+1,#start4-#start3-1)AS Third,
RIGHT(#text,#start_index_reverse-1) AS Lst

How to split a string in sql server using stored procedure and insert the data to table

<pre>update d
set d.Price = null
from dbo.SalDocumentDetail d
left join dbo.StkWarehouse w on w.WarehouseID = d.WarehouseID
where DocumentID=" + 1 + "
and DocumentTypeID=" + 2 + "
and FiscalYear= " + 2016 + "
and isnull(isPrescription,0) <>1
and w.POSType is null
and ProductName BETWEEN ''C' 'AND' 'M''
and Country LIKE ''%land%'''</pre>
Actually this string is only a sample one my original string is very large . i am not getting a point that if i break this string than how many variables i have to make to capture the data also after splitting the string i want that to be inserted into data table containing columns as Felid and Value?
I want my result like :
<pre>
Felid Value
DocumentID= 1
DocumentTypeID= 2
FiscalYear= 2016
isnull(isPrescription,0) <>= 1
w.POSType is= null
ProductName= C
ProductName= M
Country= land
</pre>
<pre>I Use this function but this function split 'and' not split like what i want in my result i want split 'and,or,like,is,between ' if function find any this split it to two columns (Felid and Value)</pre>
<pre>ALTER FUNCTION [dbo].[fnSplitString]
(#List NVARCHAR(MAX),#Delimiter NVARCHAR(255))
RETURNS #Items TABLE(Felid NVARCHAR(Max),Valu nvarchar(MAx))
WITH SCHEMABINDING
AS BEGIN
DECLARE #ll INT=LEN(#List)+1,#ld INT=LEN(#Delimiter);
WITH a AS
(SELECT
[end]=COALESCE(NULLIF(CHARINDEX(#Delimiter,#List,1),0),#ll),
[VlaueFelid]=SUBSTRING(#List,(select
CHARINDEX('where',#List)+5),COALESCE(NULLIF(CHARINDEX('=', #List,0),0),#ll) ) ,
[Value]=SUBSTRING(#List,(select CHARINDEX('="',#List)+2),(select CHARINDEX('and',#List))-(select C`enter code here`HARINDEX('="',#List)+3))
UNION ALL
SELECT
[end]=COALESCE(NULLIF(CHARINDEX(#Delimiter,#List,[end]+#ld), 0),#ll),
[VlaueFelid]=SUBSTRING(#List,[end]+#ld, COALESCE(NULLIF(CHARINDEX('=',#List, [end]+#ld),0),#ll)-[end]-#ld),
[Value]=SUBSTRING(#List,[end]+#ld+16, COALESCE(NULLIF(CHARINDEX('=',#List,[end]+#ld),0),#ll)-[end]-#ld-5)
FROM a WHERE [end]< #ll) INSERT #Items SELECT[VlaueFelid],[Value] FROM a WHERE LEN([VlaueFelid])>0 RETURN;
END</pre>

Turning an XML into a select

I'm trying to turn this XML string into a select
I have #Schedule XML = '<days><day enabled="0">0</day><day enabled="1">1</day><day enabled="1">2</day><day enabled="1">3</day><day enabled="1">4</day><day enabled="1">5</day><day enabled="0">6</day></days>'
What I'm trying to see at the end is..
DayNumber DayEnabled
0 0
1 1
2 1
3 1
4 1
5 1
6 0
I've tried a few ways, so far nothing is working right.. I am handling this as an XML data type, I'd prefer not to use a function as this will just be in a stored procedure..
Update: Maybe I didn't explain it correctly..
I have a stored procedure, XML is one of the parameters passed to it, I need to send it to a table to be inserted, so I'm trying to do the following..
INSERT INTO tblDays (DayNumber, DayEnabled)
SELECT #XMLParsedOrTempTableWithResults
I just can't figure out how to parsed the parameter
DECLARE #myXML as XML = '<days><day enabled="0">0</day><day enabled="1">1</day><day enabled="1">2</day><day enabled="1">3</day><day enabled="1">4</day><day enabled="1">5</day><day enabled="0">6</day></days>'
DECLARE #XMLDataTable table
(
DayNumber int
,DayEnabled int
)
INSERT INTO #XMLDataTable
SELECT d.value('text()[1]','int') AS [DayNumber]
,d.value('(#enabled)[1]','int') AS [DayEnabled]
FROM #myXML.nodes('/days/*') ds(d)
SELECT * FROM #XMLDataTable
Refer:
http://beyondrelational.com/modules/2/blogs/28/posts/10279/xquery-labs-a-collection-of-xquery-sample-scripts.aspx
The XMLTABLE function is how most XML-enabled DBMSes shred an XML document into a relational result set.
This example uses DB2's syntax for XMLTABLE and an input parameter passed into a stored procedure:
INSERT INTO tblDays (DayNumber, DayEnabled)
SELECT X.* FROM
XMLTABLE ('$d/days/day' PASSING XMLPARSE( DOCUMENT SPinputParm ) as "d"
COLUMNS
dayNumber INTEGER PATH '.',
dayEnabled SMALLINT PATH '#enabled'
) AS X
;