T-SQL Replace Multiple Values with Wildcards - sql

I want to replace characters , and /. I can do this with:
DECLARE #OMG VARCHAR(200)
SET #OMG = 'ABC,DE/F'
SELECT REPLACE(REPLACE(#OMG,'/','|') ,',','|')
The second query does not work however. Is there just typo or the task cannot be achieved with this code? I wanted to use wildcard for set of characters that should be replaced.
SELECT REPLACE(#OMG,[,/],'|')
It returns:
Msg 207, Level 16, State 1, Line 7
Invalid column name ',/'.

You can define all the variables to be replaced and the replacement inside a table use it.
create TABLE #ReplaceStrings (symb VARCHAR(5),replace_char varchar(5))
INSERT INTO #ReplaceStrings
(symb,replace_char)
VALUES ('/','|'),(',','|')
DECLARE #OMG VARCHAR(200)
SET #OMG = 'ABC,DE/F'
SELECT #OMG = Replace(#OMG, symb, replace_char)
FROM #ReplaceStrings
select #OMG
Here in a single replace you can replace all the unwanted characters.
Update: to replace data from table
create TABLE ReplaceStrings (symb VARCHAR(5),replace_char varchar(5))
create table #table (String varchar(500))
insert into #table values ('ABC,DE/F'),('AB,C,DE/F/')
INSERT INTO ReplaceStrings VALUES ('/','|'),(',','|')
Scalar Function
Create function replacechar(#Ip_String varchar(500))
returns varchar(500)
begin
SELECT #Ip_String=Replace(#Ip_String, symb, replace_char)
FROM ReplaceStrings
return #Ip_String
end
Execute the function
select String,dbo.replacechar(String) Replaced_String from #table

Related

Create a procedure to insert multiple values into a table, using a single variable

Goal: To create a procedure to insert multiple values into a table, using a single variable.
Challenge: Instead of making multiple hits in the same table, I have created a single variable (#SQL) and stored multiple columns (fm_id and shdl_id ) results in it but I am unable to use this single variable in the insert statement.
Code:
create proc abc
(
#org_id numeric(10,0),
#shdl_id numeric(10,0),
#usr_id numeric(10,0),
#tst_id numeric(10,0)
)
AS
BEGIN
SET NOCOUNT ON
DECLARE #SQL NUMERIC(10);
SET #SQL= (SELECT fm_id,#shdl_id FROM [dbo].[students] WHERE ORG_ID=#org_id AND shdl_id=#shdl_id AND TST_ID=#tst_id)
INSERT INTO [USER]
SELECT org_id,#usr_id,TST_ID,login_name,#SQL FROM [students] WHERE ORG_ID=#org_id AND shdl_id=#shdl_id AND TST_ID=#tst_id
END
GO
Error :
Msg 213, Level 16, State 1, Procedure abc, Line 14 [Batch Start Line
94] Column name or number of supplied values does not match table
definition.
First you need to make your SELECT return only one value into the variable. There's no point selecting #shdl_id because you already know it?
DECLARE #pFMID NUMERIC(10);
SELECT #pFMID = MAX(fm_id) FROM [dbo].[students] WHERE ORG_ID=#org_id AND shdl_id=#shdl_id AND TST_ID=#tst_id);
Then because you're not inserting a value into every column in the user table you need to explicitly state which columns to fill. Replace x1..x5 below with real column names (in the order the SELECT has them)
INSERT INTO [USER](x1,x2,x3,x4,x5)
-- ^^^^^^^^^^^^^^^
-- REPLACE THESE WITH REAL NAME
SELECT org_id,#usr_id,TST_ID,login_name,#pFMID FROM [students] WHERE ORG_ID=#org_id AND shdl_id=#shdl_id AND TST_ID=#tst_id
END
GO
And as Uueerdo pointed out, this first query is a bit of a waste of time, we can write this:
create proc abc
(
...
)
AS
BEGIN
INSERT INTO [USER](x1,x2,x3,x4,x5)
SELECT org_id,#usr_id,TST_ID,login_name,fm_id FROM [students] WHERE ORG_ID=#org_id AND shdl_id=#shdl_id AND TST_ID=#tst_id
-- ^^^^^
-- look!
You can only get away with leaving the column list off an INSERT if you're inserting the same number of columns the table has:
CREATE TABLE x(col1 INT, col2 INT);
INSERT INTO x VALUES (1,2) -- works
INSERT INTO x VALUES (1) -- fails: which column should have the 1?
INSERT INTO x(col1) VALUES (1) -- works: col1 shall have the 1

How to store multiple values in a SQL Server variable

I want to store values from a SELECT statement into a variable which is capable of holding more than one value because my SELECT statement returns multiple values of type INT. This is how my SP looks like so far.
ALTER PROCEDURE "ESG"."SP_ADD"
AS
BEGIN
DECLARE #Id table(identifiers VARCHAR);
INSERT INTO #Id (identifiers) VALUES('axaa1aaa-aaaa-a5aa-aaaa-aa8aaaa9aaaa');
INSERT INTO #Id (identifiers) VALUES('bxbb1bbb-bbbb-b5bb-bbb4-bb8bbbb9bbbf');
DECLARE #tranID INT = (SELECT
DOCUMENT_SET_.DOCUMENT_SET_TRANSACTION_ID
FROM DOCUMENT_SET_TRANSACTION
WHERE DOCUMENT_SET_TRANSACTION.IDENTIFIER IN (SELECT identifiers FROM #Id));
END
Variable #tranID should be a list or an array to hold the ids. Is it possible to do it SQL Server?
You can declare a variable of type table
DECLARE #tblTrans TABLE (
tranID INT
);
INSERT INTO #tblTrans
SELECT DOCUMENT_SET_TRANSACTION.DOCUMENT_SET_TRANSACTION_ID
FROM ESG.DOCUMENT_SET_TRANSACTION
WHERE DOCUMENT_SET_TRANSACTION.IDENTIFIER
IN (SELECT identifiers FROM #envelopeId);
Depending on what you want to do with the values after this, you could declare a cursor to loop through them or select straight from the variable.
You could also look into using a temporary table depending on what scope you need.
Try this, only take the firs row of example. Do u try this?
select DOCUMENT_SET_TRANSACTION.DOCUMENT_SET_TRANSACTION_ID,
(STUFF((SELECT '-' + convert(varchar(max),DOCUMENT_SET_TRANSACTION.DOCUMENT_SET_TRANSACTION_ID)
FROM ESG.DOCUMENT_SET_TRANSACTION
FOR XML PATH ('')), 1, 2, '')) AS example
FROM ESG.DOCUMENT_SET_TRANSACTION

T-SQL select special characters from nvarchar field

I'm looking for a select statement in which I can refine values in a nvarchar field.
For example: the input value is '!ab>c2 ghf5 ksj#_+wwl9' and output must be 'abc ghf ksjwwl'. How can I remove some extra characters within a text with SQL regex or other ways?
I don't know if this helps, but you can define a table with all characters / phrases you want to replace and do it like this:
DECLARE #CharsToReplace TABLE(SearchFor VARCHAR(100),ReplaceWith VARCHAR(100));
INSERT INTO #CharsToReplace VALUES('1',''),('2',''),('3',''),('4',''),('5',''),('6',''),('7',''),('8',''),('9',''),('0','');
DECLARE #YourString VARCHAR(100)='abc2 ghf5 ksjwwl9';
SELECT #YourString=REPLACE(#YourString,SearchFor,ReplaceWith)
FROM #CharsToReplace;
SELECT #YourString;
The result
abc ghf ksjwwl
If you'd define values in ReplaceWith this would work too.
UPDATE A function you can use in any select
Attention: This will be slow!
CREATE FUNCTION dbo.DeleteChars(#CharList NVARCHAR(MAX),#string NVARCHAR(MAX))
RETURNS NVARCHAR(MAX)
AS
BEGIN
DECLARE #List XML=(SELECT CAST('<x>'+ REPLACE(#CharList,',','</x><x>')+'</x>' AS XML));
SELECT #string=REPLACE(#string,ch.value(N'.',N'nvarchar(max)'),'')
FROM #List.nodes('/x') AS A(ch);
RETURN #string;
END
GO
--Test this with a mock-up table
DECLARE #SomeTable TABLE(SomeColumn VARCHAR(100));
INSERT INTO #SomeTable VALUES('abc2 ghf5 ksjwwl9'),('123 abc 456 hello');
--This is the char list (comma separated)
DECLARE #CharList VARCHAR(100)='1,2,3,4,5,6,7,8,9,0';
--This is how you call it
SELECT dbo.DeleteChars(#CharList,SomeColumn)
FROM #SomeTable
GO
--Clean up
DROP FUNCTION dbo.DeleteChars;
The result
abc ghf ksjwwl
abc hello

How to run SQL Server stored procedure query for each value of a CSV

I am having following stored procedure in my SQL Server 2008 R2 database
ALTER PROCEDURE [dbo].[usp_send_email]
#pStatus Int Out,
#pEMailId Int Out,
#pSenderUserName varchar(MAX),
#pReceivers VarChar(50), **-- this column can have csv values**
#pSub NVarChar(100),
#pCon NVarchar(MAX),
#pHasAttachments Bit
AS
BEGIN
--SET NOCOUNT ON;
Insert Into MessagingMessage
(
CreatedBy,
[Subject],
Body,
HasAttachments
)
Values
(
#pSenderUserName,
#pSub,
#pCon,
#pHasAttachments
)
SET #pEMailId = SCOPE_IDENTITY()
Insert Into MessagingMessageReceipient
(
MessageId,
ReceipientId,
ReceipientType
)
Values
(
#pEMailId,
#pReceivers,
1
)
SET #pStatus = SCOPE_IDENTITY()
END
In above code I want to run the first statement only one time but second insert statements in loop for each comma separated username.CSV value coming as a parameter is already validated by C# code so no need to validate it.
Using this link: how to split and insert CSV data into a new table in single statement?, there is a function you can use to parse csv to to table and I have used it in the code below. Try the following
Insert Into MessagingMessageReceipient
(
MessageId,
ReceipientId,
ReceipientType
)
SELECT
#pEMailId,
csv.Part, -- each #pReceiver
1
FROM
dbo.inline_split_me(',',#pReceivers) csv
And the function is copied below
CREATE FUNCTION inline_split_me (#SplitOn char(1),#String varchar(7998))
RETURNS TABLE AS
RETURN (WITH SplitSting AS
(SELECT
LEFT(#String,CHARINDEX(#SplitOn,#String)-1) AS Part
,RIGHT(#String,LEN(#String)-CHARINDEX(#SplitOn,#String)) AS Remainder
WHERE #String IS NOT NULL AND CHARINDEX(#SplitOn,#String)>0
UNION ALL
SELECT
LEFT(Remainder,CHARINDEX(#SplitOn,Remainder)-1)
,RIGHT(Remainder,LEN(Remainder)-CHARINDEX(#SplitOn,Remainder))
FROM SplitSting
WHERE Remainder IS NOT NULL AND CHARINDEX(#SplitOn,Remainder)>0
UNION ALL
SELECT
Remainder,null
FROM SplitSting
WHERE Remainder IS NOT NULL AND CHARINDEX(#SplitOn,Remainder)=0
)
SELECT Part FROM SplitSting
)

SQL How to find if all values from one field exist in another field in any order

I am trying to match data from an external source to an in house source. For example one table would have a field with a value of "black blue" and another table would have a field with a value of "blue black". I am trying to figure out how to check if all individual words in the first table are contained in a record the 2nd table in any order. It's not always two words that need to be compared it could be 3 or 4 as well. I know I could use a cursor and build dynamic sql substituting the space with the AND keywod and using the contains function but I'm hoping not to have to do that.
Any help would be much appreciated.
Try doing something like this: Split the data from the first table on the space into a temporary table variable. Then use CHARINDEX to determine if each word is contained in the second table's record. Then just do this for each word in the first record and if the count is the same as the successful checks then you know every word from the first record is used in the second.
Edit: Use a Split function such as:
CREATE FUNCTION dbo.Split (#sep char(1), #s varchar(512))
RETURNS table
AS
RETURN (
WITH Pieces(pn, start, stop) AS (
SELECT 1, 1, CHARINDEX(#sep, #s)
UNION ALL
SELECT pn + 1, stop + 1, CHARINDEX(#sep, #s, stop + 1)
FROM Pieces
WHERE stop > 0
)
SELECT pn,
SUBSTRING(#s, start, CASE WHEN stop > 0 THEN stop-start ELSE 512 END) AS s
FROM Pieces
)
Here's another method you could try, you could sample some simple attributes of your strings such as, length, number of spaces, etc.; then you could use a cross-join to create all of the possible string match combinations.
Then within your where-clause you can sort by matches, the final piece of which in this example is a check using the patindex() function to see if the sampled piece of the first string is in the second string.
-- begin sample table variable set up
declare #s table(
id int identity(1,1)
,string varchar(255)
,numSpace int
,numWord int
,lenString int
,firstPatt varchar(255)
);
declare #t table(
id int identity(1,1)
,string varchar(255)
,numSpace int
,numWord int
,lenString int
);
insert into #t(string)
values ('my name');
insert into #t(string)
values ('your name');
insert into #t(string)
values ('run and jump');
insert into #t(string)
values ('hello my name is');
insert into #s(string)
values ('name my');
insert into #s(string)
values ('name your');
insert into #s(string)
values ('jump and run');
insert into #s(string)
values ('my name is hello');
update #s
set numSpace = len(string)-len(replace(string,' ',''));
update #s
set numWord = len(string)-len(replace(string,' ',''))+1;
update #s
set lenString = len(string);
update #s
set firstPatt = rtrim(substring(string,1,charindex(' ',string,0)));
update #t
set numSpace = len(string)-len(replace(string,' ',''));
update #t
set numWord = len(string)-len(replace(string,' ',''))+1;
update #t
set lenString = len(string);
-- end sample table variable set up
-- select all combinations of strings using a cross join
-- and sort the entries in your where clause
-- the pattern index checks to see if the sampled string
-- from the first table variable is in the second table variable
select *
from
#s s cross join #t t
where
s.numSpace = t.numspace
and s.numWord = t.numWord
and s.lenString = t.lenString
and patindex('%'+s.firstPatt+'%',t.string)>0;