SQL WHILE (String manipulation) - sql-server

I got a text string consists of 38 chars or so, and i want to search for that string in the database in a specific column. If there is a match, i want the corresponding value from another column as result. If no match is found, i want the string to get cut off by one char from the right hand side, and a new match search performed. This should repeat until either a match if found OR i'm running out of characters
Can anyone please point me in the right direction?
This is the code i made so far, but it's not really doing what i expect it to:
SET NOCOUNT ON
DECLARE #ITEM VARCHAR(38)
DECLARE #CTR INT = 0
DECLARE #RES VARCHAR(40)
SET #ITEM = 'KLS3055P3H01T01A3913 STDP STDP V2 SOMO'
SET #RES = NULL
WHILE #RES IS NULL
BEGIN
SET #RES = (SELECT A.a_nr FROM spekgbp.dbo.art A WHERE A.a_bet LIKE #ITEM)
SET #ITEM = LEFT(#ITEM, LEN(#ITEM)-1)
SET #CTR = #CTR + 1
IF (#CTR =10)
BREAK
END
SELECT #RES as 'RES', #ITEM as 'ITEM'

This is my proposal, if I understand you correctly:
SET NOCOUNT ON
DECLARE #ITEM VARCHAR(38)
DECLARE #CTR INT = 0
DECLARE #RES VARCHAR(40)
SET #ITEM = 'KLS3055P3H01T01A3913 STDP STDP V2 SOMO'
SET #RES = NULL
WHILE (1 = 1)
BEGIN
SET #RES = (SELECT MIN(A.a_nr) FROM spekgbp.dbo.art A WHERE A.a_bet = #ITEM)
IF (#RES IS NOT NULL)
BEGIN
BREAK
END
SET #ITEM = LEFT(#ITEM, LEN(#ITEM)-1)
SET #CTR = #CTR + 1
IF (#CTR = 10)
BEGIN
BREAK
END
END
SELECT #RES as 'RES', #ITEM as 'ITEM'
I added the infinate loop, because when match is found #ITEM is still cut at the end, and in my way loop breaks immediately after #RES is found.

Related

Split String Returning only first value

My split string code is only returning the first value for some reason. I cannot figure this out so any help would be appreciated. I am using the following.
declare #CYEnd varchar(4) = '2015, 2016, 2017'
SELECT * FROM vwRMSGrantsSpending
WHERE CYEnd IN (select ltrim(item) from dbo.SplitStringList(#CYEnd, ','))
This should be returning 2015, 2016, and 2017. But it is only returning 2015.
Here is dbo.SplitStringList
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[SplitStringList](#ListString nvarchar(max), #delim
varchar(2) = ',')
returns #vals table (Item nvarchar(60))
as
begin
declare #CurLoc int, #Item nvarchar(60)
while len(#ListString) > 0
begin
set #CurLoc = charindex(#delim, #ListString, 1)
if #CurLoc = 0
begin
set #Item = #ListString
set #Item = Ltrim(RTrim(#Item))
set #ListString = ''
end
else
begin
set #Item = left(#ListString, #CurLoc - 1)
set #Item = Ltrim(RTrim(#Item))
set #ListString = substring(#ListString, #CurLoc + 1,
Len(#ListString) - #CurLoc)
end
insert into #vals (Item) values (#Item)
end
return
end
The problem is that you defined the varchar too small.
declare #CYEnd varchar(4) = '2015, 2016, 2017'
If you run this PRINT #CYEnd after the declare you will see that the variable is only equal to 2015.
Make that variable bigger and it works.

Get range of new record insert in SQL Server

I have send data from downstream to cloud services and it will insert to Cloud SQL Services.
But, currently the data is send up to 12 data per seconds for some hours. The data contains DeviceID, Timestamp, HexData etc. and will be save in tbl_highspeeddata. Trigger has been created to convert the value of Hex data to ASCII string on this table.
The converting is work good if the data come in with some interval. As for now, there is only less hex data converted as I'm currently stuck on how to make it select range of new row inserted from last get until latest and do converting one-by-one before update back to the column.
After it finish, it will take from the the first new data after previous last processed data until the latest inserted record and repeat converting.
I have tried INSTEAD OF trigger
SELECT TOP n [primaryKey], *
FROM table
ORDER BY [primaryKey] DESC
SELECT SCOPE_IDENTITY();
and all failed to convert and update every inserted row.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[HSHD_Data_Conversion]
ON [dbo].[HSHD]
AFTER INSERT
AS
BEGIN
/****** HSHD stand for High Speed Hex Data ******/
---------convert HEX to ASCII
DECLARE #ID INT
DECLARE #HEX VARCHAR(MAX)
SET #ID = (SELECT SCOPE_IDENTITY()) --(SELECT TOP 1 ID from HSHD ORDER BY DateCreated DESC)
SET #HEX = (select CONVERT(varbinary(max), Data, 2) from HSHD WHERE ID = #ID)
UPDATE HSHD
SET Data = #HEX
WHERE ID = #ID
---------split command, query and result
DECLARE #Delimiter VARCHAR(8000)
DECLARE #Item VARCHAR(8000)
DECLARE #ItemList VARCHAR(8000)
DECLARE #DelimIndex INT
DECLARE #RowID INT
DECLARE #counter INT
DECLARE #isQuery VARCHAR(1)
SET #RowID = (SELECT SCOPE_IDENTITY()) --(SELECT TOP 1 ID FROM HSHD ORDER BY ID DESC)
SET #ItemList = (SELECT Data FROM HSHD WHERE ID = #RowID)
SET #counter = 0
SET #Delimiter = ':'
SET #DelimIndex = CHARINDEX(#Delimiter, #ItemList, 0)
WHILE (#DelimIndex != 0)
BEGIN
SET #counter = #counter + 1
SET #Item = SUBSTRING(#ItemList, 0, #DelimIndex)
--ignore the first element
IF #counter != 1
BEGIN
SET #isQuery = CHARINDEX('?',#Item,0)
IF len(#Item) != 0
BEGIN
IF #isQuery != 0
BEGIN
INSERT INTO HSHD_Data(HSHD,Query) VALUES (#RowID,':' + #Item)
END
ELSE INSERT INTO HSHD_Data(HSHD,Command) VALUES (#RowID, ':' + #Item)
END
END
-- Set #ItemList = #ItemList minus one less item
SET #ItemList = SUBSTRING(#ItemList, #DelimIndex+1, LEN(#ItemList)-#DelimIndex)
SET #DelimIndex = CHARINDEX(#Delimiter, #ItemList, 0)
SET #counter = #counter + 1
END -- End WHILE
IF #Item IS NOT NULL -- At least one delimiter was encountered in #InputString
BEGIN
SET #Item = #ItemList
SET #isQuery = CHARINDEX('?',#Item,0)
IF len(#Item) != 0
BEGIN
IF #isQuery != 0
BEGIN
INSERT INTO HSHD_Data(HSHD,Query) VALUES (#RowID,':' + #Item)
END
ELSE INSERT INTO HSHD_Data(HSHD,Command) VALUES (#RowID, ':' + #Item)
END
END
ELSE
BEGIN
SET #isQuery = CHARINDEX('?',#ItemList,0)
IF #isQuery != 0
INSERT INTO HSHD_Data(HSHD,Query) VALUES (#RowID, #ItemList)
ELSE
INSERT INTO HSHD_Data(HSHD,Result) VALUES (#RowID, #ItemList)
END
END
My reference:
Instead Of
Newly Added Row
EDITED:
HSHD data before trigger run:
HSHD data after trigger run:
So, after trigger finish running and convert these 2 data, trigger will start grab for data after :SYSTem:ERRor! #STRing until the last and converted hex and update back ASCII value to the HEX data.

Conversion failed when converting the varchar value ',1,2,3' to data type int

This error results when attempting to use a comma delimited parameter in an IN condition
I'm passing a varchar parameter to a stored procedure that looks like this
,1,2,3
And I want to find out if it contains 1 (it doesn't always contain 1)
What's the easiest way to do that in TSQL ?
declare #Nums varchar(max)=',1,2,3'
if 1 in (#Nums) -- conversion error
BEGIN
select * from TestTable
END
You will need to use LIKE to see if the string contains the character 1. Note this will also match 12 or any string with the character '1' in it.
declare #Nums varchar(max)=',1,2,3'
if #Nums LIKE '%1%'
BEGIN
select * from TestTable
END
If you need to match the full number:
CREATE FUNCTION [dbo].[Split_String]
(
#ItemList NVARCHAR(4000),
#delimiter CHAR(1)
)
RETURNS #IDTable TABLE (Item VARCHAR(50))
AS
BEGIN
DECLARE #tempItemList NVARCHAR(4000)
SET #tempItemList = #ItemList
DECLARE #i INT
DECLARE #Item NVARCHAR(4000)
SET #tempItemList = REPLACE (#tempItemList, ' ', '')
SET #i = CHARINDEX(#delimiter, #tempItemList)
WHILE (LEN(#tempItemList) > 0)
BEGIN
IF #i = 0
SET #Item = #tempItemList
ELSE
SET #Item = LEFT(#tempItemList, #i - 1)
INSERT INTO #IDTable(Item) VALUES(#Item)
IF #i = 0
SET #tempItemList = ''
ELSE
SET #tempItemList = RIGHT(#tempItemList, LEN(#tempItemList) - #i)
SET #i = CHARINDEX(#delimiter, #tempItemList)
END
RETURN
END
DECLARE #Nums VARCHAR(MAX) = ',1,2,3'
DECLARE #NumberTable TABLE (item INT)
INSERT INTO #NumberTable
SELECT TRY_CAST(Item AS INT)
FROM dbo.Split_String(#Nums, ',')
IF (SELECT 1 FROM #NumberTable WHERE item = 1) = 1
BEGIN
select * from TestTable
END
You can use CHARINDEX.
declare #Nums varchar(max)=',1,2,3'
IF CHARINDEX(',1,', #Nums+',') > 0
BEGIN
select * from TestTable
END

How to insert a comma separated values to the column to a SQL table in a order same as passing order?

i written a code like below to insert a comma separated values to the tempTble.It is working but i need the values to be entered in a order same as am passing it to query.But here number are arranged in a numerical order and string values arranged according to alphabetical order .Example '7,6,5,1,2,Jack,Ana,Micky' but it is inserted to column in a order of '1,2,5,6,7,Ana,Jack,Micky'.
Can you please provide answer for this.
Thank you in advance
ALTER PROCEDURE [dbo].[usp_GetValuesFromBillingSystem]
(
#BillingSystemCode VARCHAR(max)
)
AS
BEGIN
DECLARE #planID varchar(max) = Null ;
SET #planID= #BillingSystemCode
DECLARE #tempTble Table (planID varchar(50) NULL);
while len(#planID ) > 0
begin
insert into #tempTble (planID ) values(left(#planID , charindex(',', #planID +',')-1))
set #planID = stuff(#planID , 1, charindex(',', #planID +','), '')
end
select * from #tempTble
END
www.aspdotnet-suresh.com/2013/07/sql-server-split-function-example-in.html
CREATE FUNCTION dbo.Split(#String nvarchar(4000), #Delimiter char(1))
RETURNS #Results TABLE (Items nvarchar(4000))
AS
BEGIN
DECLARE #INDEX INT
DECLARE #SLICE nvarchar(4000)
-- HAVE TO SET TO 1 SO IT DOESNT EQUAL Z
-- ERO FIRST TIME IN LOOP
SELECT #INDEX = 1
WHILE #INDEX !=0
BEGIN
-- GET THE INDEX OF THE FIRST OCCURENCE OF THE SPLIT CHARACTER
SELECT #INDEX = CHARINDEX(#Delimiter,#STRING)
-- NOW PUSH EVERYTHING TO THE LEFT OF IT INTO THE SLICE VARIABLE
IF #INDEX !=0
SELECT #SLICE = LEFT(#STRING,#INDEX - 1)
ELSE
SELECT #SLICE = #STRING
-- PUT THE ITEM INTO THE RESULTS SET
INSERT INTO #Results(Items) VALUES(#SLICE)
-- CHOP THE ITEM REMOVED OFF THE MAIN STRING
SELECT #STRING = RIGHT(#STRING,LEN(#STRING) - #INDEX)
-- BREAK OUT IF WE ARE DONE
IF LEN(#STRING) = 0 BREAK
END
RETURN
END

SQL single row to multiple rows separated by comma

I would like to get a list of data from SQL Server including the data separated by comma in new rows.
Note : I have only single column name DATA
I have a value like
DATA
new
old,yes,now
ok,for
no
My required output is:
DATA
new
old
yes
now
ok
for
no
What you need is a split functions , Just see if this works for you
CREATE FUNCTION FNC_SPLIT(#MYSTR VARCHAR(500), #DELIMITER CHAR(1))
RETURNS #MYTBL TABLE (idx smallint, value varchar(8000))
AS
BEGIN
DECLARE #RET VARCHAR(500)
DECLARE #INDEX INT
DECLARE #COUNTER smallint
--Get the first position of delimiter in the main string
SET #INDEX = CHARINDEX(#DELIMITER,#MYSTR)
SET #COUNTER = 0
--Loop if delimiter exists in the main string
WHILE #INDEX > 0
BEGIN
--extract the result substring before the delimiter found
SET #RET = SUBSTRING(#MYSTR,1, #INDEX-1 )
--set mainstring right part after the delimiter found
SET #MYSTR = SUBSTRING(#MYSTR,#INDEX+1 , LEN(#MYSTR) - #INDEX )
--increase the counter
SET #COUNTER = #COUNTER + 1
--add the result substring to the table
INSERT INTO #MYTBL (idx, value)
VALUES (#COUNTER, #RET)
--Get the next position of delimiter in the main string
SET #INDEX = CHARINDEX(#DELIMITER,#MYSTR)
END
--if no delimiter is found then simply add the mainstring to the table
IF #INDEX = 0
BEGIN
SET #COUNTER = #COUNTER + 1
INSERT INTO #MYTBL (idx, value)
VALUES (#COUNTER, #MYSTR)
END
RETURN
END
GO
declare #table table(dt varchar(100));
insert into #table values
('DATA'),
('new'),
('old,yes,now'),
('ok,for');
select * from #table
select value from #table t cross apply dbo.FNC_SPLIT(t.dt,',')

Resources