T-SQL input parameter as stringArray() - sql

I am writing update query
"Update tbl_List Set ListName = 'Hello' where ListId IN (stringArray()).
I have added 5 string values in stringArray() and how to pass it as input parameter to SQL ? How to execute query with Array values?

You can create your query as :
Update tbl_List Set ListName = 'Hello' where ListId IN ('value1' , 'value2' ,'valueN');
Or using a table :
Declare #Val Table (IDs Nvarchar(50) );
Insert into #val values ('value1'),('value2'),('valueN');
Update tbl_List Set ListName = 'Hello' where ListId IN (Select IDs From #Val);
You can loop in your StringArray to pass values , and you can use only one parametre and excute your query as much as the length of your Array.
Also you can use temp tables for that job.

Related

How can I replace multiple words of a string in SQL

Is it possible to replace multiple words in a string in sql without using multiple replace functions?
For example I have a string where I need to replace word 'POLYESTER' with 'POLY' , 'COTTON' with 'CTN', 'GRAPHIC' with 'GRPHC' etc in order to keep the string length at a max of say 30 without much loosing the readability of contents in it(can't use substring to limit chars since it can trim the end meaningful parts of string completely). So we decided to short some keywords like above.
Current query I have used :
SELECT
REPLACE(REPLACE('**Some string value **COTTON **Some string value ** POLYESTER', 'POLYESTER', 'POLY'), 'COTTON', 'CTN')
If I have 10 keywords like this, what will be the best way to achieve the result other than using multiple replace function. I am using SQL Server 2012.
considering sql server is your only instrument (not a c# or another application), as a workaroud; use a temp or persistent table to store replacement options.
IF OBJECT_ID('tempdb..#tmp') IS NOT NULL
DROP TABLE #tmp
CREATE TABLE #tmp (
fromText VARCHAR(16),
toText VARCHAR(16)
);
INSERT INTO #tmp (fromText, toText)
VALUES
('POLYESTER', 'POLY'),
('COTTON', 'CTN'),
('GRAPHIC', 'GRPHC')
DECLARE #someValue AS NVARCHAR(MAX) =
'**Some string value **COTTON **Some string value ** POLYESTER';
SELECT #someValue = REPLACE(#someValue, fromText, toText) FROM #tmp;
PRINT #someValue
and the result is:
**Some string value **CTN **Some string value ** POLY.
The answer of mehmetx is actually very nice.
If you need your replacement functionality on a regular basis, you could think about using a normal table instead of a temporary table.
But if you need this logic only once in a while, and performance is not much of an issue, you could avoid the additional replacements table altogether and use a table expression in the FROM clause instead. Something like this:
DECLARE #someValue AS NVARCHAR(MAX) = '**Some string value **COTTON **Some string value ** POLYESTER';
SELECT #someValue = REPLACE(#someValue, fromText, toText)
FROM
(VALUES
('POLYESTER', 'POLY'),
('COTTON', 'CTN'),
('GRAPHIC', 'GRPHC')
) AS S (fromText, toText);
EDIT:
I noticed, that this logic regrettably does not work as expected when used in an UPDATE statement to update existing data in a table.
For that purpose (if needed), I created a user-defined function that performs the replacement logic. I called it MultiReplace. And it does not use the replacement data from a temporary table, but from a "normal" table, which I called Replacements.
The following code demonstrates it. It uses a data table called MyData, which gets updated with all replacements in the Replacements table using the MultiReplace function:
IF OBJECT_ID('MultiReplace') IS NOT NULL
DROP FUNCTION MultiReplace;
IF OBJECT_ID('Replacements') IS NOT NULL
DROP TABLE Replacements;
IF OBJECT_ID('MyData') IS NOT NULL
DROP TABLE MyData;
GO
CREATE TABLE Replacements (
fromText VARCHAR(100),
toText VARCHAR(100)
);
CREATE TABLE MyData (
SomeValue VARCHAR(MAX)
)
GO
CREATE FUNCTION MultiReplace(#someValue AS VARCHAR(MAX))
RETURNS VARCHAR(MAX)
AS
BEGIN
SELECT #someValue = REPLACE(#someValue, fromText, toText) FROM Replacements;
RETURN #someValue;
END;
GO
INSERT INTO MyData (SomeValue)
VALUES
('**Some string value **COTTON **Some string value ** POLYESTER');
INSERT INTO Replacements (fromText, toText)
VALUES
('POLYESTER', 'POLY'),
('COTTON', 'CTN'),
('GRAPHIC', 'GRPHC');
SELECT * FROM MyData;
UPDATE MyData SET SomeValue = dbo.MultiReplace(SomeValue)
SELECT * FROM MyData;
But perhaps using multiple REPLACE statements might be more straightforward after all?...
EDIT 2:
Based on the short conversation in the comments, I could propose a simpler solution that uses multiple REPLACE statements in a clearer way. I have only tested it on SQL Server 2019; I am not sure if it will work correctly on SQL Server 2012.
Again, I use a table called MyData for testing here. But there are no additional database objects anymore.
Regrettably, I did not get it to work with a temporary table containing the replacement values.
-- Preparations:
IF OBJECT_ID('MyData') IS NOT NULL
DROP TABLE MyData;
CREATE TABLE MyData (
SomeValue VARCHAR(MAX)
);
INSERT INTO MyData
VALUES
('**Some string value **COTTON **Some string value ** POLYESTER'),
('**Another string value **GRAPHIC **Another string value ** POLYESTER');
-- Actual work:
SELECT * FROM MyData; -- Show the state before updating
DECLARE #someValue VARCHAR(MAX);
UPDATE MyData
SET
#someValue = SomeValue,
#someValue = REPLACE(#someValue, 'POLYESTER', 'POLY'),
#someValue = REPLACE(#someValue, 'COTTON', 'CTN'),
#someValue = REPLACE(#someValue, 'GRAPHIC', 'GRPHC'),
SomeValue = #someValue;
SELECT * FROM MyData; -- Show the state after updating

Dynamic WHERE clause in T-SQL

I have a requirement to display reports if a field value or a combination of field value matches.
I have designed a table to store ReportId values against a field or a combination of fields. I have stored the values in a pattern so that I can construct the WHERE clause for SQL to fetch desired data. Following is the table data:
Field1 Field2 Field3 ReportId
2 NULL NULL Rep1
5 4 NULL Rep2
6 NULL 8 Rep4
Now, I want to create a stored procedure to fetch relevant ReportIds. In the stored procedure I have following parameters as input:
Parameter1, Parameter2, Parameter3
In the stored procedure, I want to construct a SQL with a dynamic WHERE clause to fetch ReportIds. The WHERE clause will put a AND operator between all NON NULL fields and compare with the passed parameters.
As per the given table data, the non-null field in first row is “Field1”. So the WHERE clause will be
Field1 = Parameter1
As per the given table data, the non-null fields in the second row is “Field1” and “Field2”. So WHERE clause will be:
Field1 = Parameter1 AND Field2 =Parameter2
As per the given table data, the non-null fields in the third row is “Field1” and “Field3”. So the WHERE clause will be:
Field1 = Parameter1 AND Field3 =Parameter3
How I can write a generic SQL with a dynamic WHERE clause for this requirement?
Le sigh.
The solution I am thinking of is a simple:
WHERE (Field1 IS NULL OR Field1=#Parameter1)
AND (Field2 IS NULL OR Field2=#Parameter2)
AND ...
You can stack any number of field/parameter pairings into this solution.
You can construct the query by appending the where clause to NVARCHAR(MAX) variable and then execute that query with sql built in function sp_executesql
For Example
DECLARE #query NVARCHAR(MAX);
SET #query = 'SELECT #Count = COUNT(*) FROM Reports WHERE 1=1 '
IF #Field1 IS NOT NULL
SET #query = #query + 'AND Field1 = #Field1 '
......
......
......
EXECUTE sp_executesql #query,
N'#Field1 VARCHAR(MAX),
....
....
#Param1,
.....
.....
I hope this helps you get the right direction.
If you think about what you are looking for and restate your question it becomes easier. What do you really want to do? You want to include rows where each field matches the parameter passed, or whether the value in the table is null. So you want to match rows where each field is either null, or it matches the parameter:
WHERE (Field1 is null OR Field1 = #Parameter1)
AND (Field2 is null OR Field2 = #Parameter2)
AND (Field3 is null OR Field3 = #Parameter2)

Need help in parsing json string in SQL stored procedure and accessing its attribute's value

I want to parse json string coming from request, extract particular information from that string and then based on that information need to call relevant update statements.
In java service it would be bit tedious to do this task as need to send each parameter separately and call relevant update statements.
If I can do the same task in stored procedure then it would be efficient. is there any way I can parse this same json string in a SQL stored procedure and update corresponding fields of tables by value of related attributes ?
Sample json string is -
{"category1":{"field1":"value1","field2":"value2"}}
this I want to send as a parameter of stored procedure
and I want to call update statement to update fields of related table with value1 and value2.
How can I parse these values in stored procedure from json string that I pass as a parameter to it?
I know this would be better off as a comment but I currently don't have that many rep points..
With that said you could try comma-schema.
I noticed this article using it.. I think you could use it to do the same.
Basically create data like the above article then update as needed
Definitely you can use JSON in a Stored procedure. This is a best way to make your DB closer to REST APIs. Your Stored procedure can have input and output both as JSON. It is just that you have to put efforts in writing a good stored procedure. rather than exposing a random access to API/user for querying it directly
here is one of the example:
DECLARE #out VARCHAR(max) =''
EXEC csdm.your_sp
#input = <your_JSON_string>,
#output = #out OUTPUT
SELECT #out
Now to achieve this write your SP as
CREATE PROCEDURE dbo.your_sp
#input VARCHAR(max),
#output VARCHAR(max) OUTPUT
AS
PRINT 'PROC_START : dbo.your_sp'
-- Declare variables as needed
DECLARE #sp_output VARCHAR(max)
DECLARE #json_category VARCHAR(max)
DECLARE #json_category VARCHAR(max)
-- Validate JSON
IF(ISJSON(#input) = 0)
BEGIN
SET #sp_output = '{"status":"Error","errorTitle":"Invalid Input JSON","errorMessage":"JSON sent as input is Incorrect, please verify and fix"}'
END
ELSE
BEGIN
-- Process JSON if valid JSON provided
-- Option 1
INSERT INTO myTable
(Field1, Field2)
VALUES
(
SELECT [VALUE] FROM OPENJSON(#op, '$.category1') where [KEY] = 'field1',
SELECT [VALUE] FROM OPENJSON(#op, '$.category1') where [KEY] = 'field1'
)
SET #sp_output = '{"status":"Success", "message":"Record updated successfully"}'
-- Option 2 : Can have more validation for the data
SELECT #json_category = VALUE FROM OpenJson (#input, '$') WHERE [Key] = 'category1'
SELECT #json_field_value = VALUE FROM OpenJson (#json_category, '$') WHERE [Key] = 'field1'
IF(#json_category IS NOT NULL OR #json_category <> '') AND (#json_field_value IS NOT NULL OR #json_field_value <> '')
BEGIN
INSERT INTO myTable
(Field1, Field2)
VALUES
(
SELECT [VALUE] FROM OPENJSON(#op, '$.category1') where [KEY] = 'field1',
SELECT [VALUE] FROM OPENJSON(#op, '$.category1') where [KEY] = 'field1'
)
SET #sp_output = '{"status":"Success", "message":"Record updated successfully"}'
END
ELSE
BEGIN
SET #sp_output = '{"status":"Error","errorTitle":"Blank/Missing Input provided","errorMessage":"Critical / Mandatory data is missing in the input JSON"}'
END
END
-- Build Output or Error response
SET #output = #sp_output
PRINT 'PROC_END : dbo.your_sp'
RETURN
GO
This is just a sample to show how to use JSON, you can do a lot more in this additionally

UPDATE and REPLACE part of a string

I've got a table with two columns, ID and Value. I want to change a part of some strings in the second column.
Example of Table:
ID Value
---------------------------------
1 c:\temp\123\abc\111
2 c:\temp\123\abc\222
3 c:\temp\123\abc\333
4 c:\temp\123\abc\444
Now the 123\ in the Value string is not needed. I tried UPDATE and REPLACE:
UPDATE dbo.xxx
SET Value = REPLACE(Value, '%123%', '')
WHERE ID <= 4
When I execute the script SQL Server does not report an error, but it does not update anything either. Why is that?
You don't need wildcards in the REPLACE - it just finds the string you enter for the second argument, so the following should work:
UPDATE dbo.xxx
SET Value = REPLACE(Value, '123', '')
WHERE ID <=4
If the column to replace is type text or ntext you need to cast it to nvarchar
UPDATE dbo.xxx
SET Value = REPLACE(CAST(Value as nVarchar(4000)), '123', '')
WHERE ID <=4
Try to remove % chars as below
UPDATE dbo.xxx
SET Value = REPLACE(Value, '123', '')
WHERE ID <=4
To make the query run faster in big tables where not every line needs to be updated, you can also choose to only update rows that will be modified:
UPDATE dbo.xxx
SET Value = REPLACE(Value, '123', '')
WHERE ID <= 4
AND Value LIKE '%123%'
query:
UPDATE tablename
SET field_name = REPLACE(field_name , 'oldstring', 'newstring')
WHERE field_name LIKE ('oldstring%');
You have one table where you have date Code which is seven character something like
"32-1000"
Now you want to replace all
"32-"
With
"14-"
The SQL query you have to run is
Update Products Set Code = replace(Code, '32-', '14-') Where ...(Put your where statement in here)
For anyone want to replace your script.
update dbo.[TABLE_NAME] set COLUMN_NAME= replace(COLUMN_NAME, 'old_value', 'new_value') where COLUMN_NAME like %CONDITION%
CREATE TABLE tbl_PersonalDetail
(ID INT IDENTITY ,[Date] nvarchar(20), Name nvarchar(20), GenderID int);
INSERT INTO Tbl_PersonalDetail VALUES(N'18-4-2015', N'Monay', 2),
(N'31-3-2015', N'Monay', 2),
(N'28-12-2015', N'Monay', 2),
(N'19-4-2015', N'Monay', 2)
DECLARE #Date Nvarchar(200)
SET #Date = (SELECT [Date] FROM Tbl_PersonalDetail WHERE ID = 2)
Update Tbl_PersonalDetail SET [Date] = (REPLACE(#Date , '-','/')) WHERE ID = 2
you should use the below update query
UPDATE dbo.xxx SET Value=REPLACE(Value,'123\','') WHERE Id IN(1, 2, 3, 4)
UPDATE dbo.xxx SET Value=REPLACE(Value,'123\','') WHERE Id <= 4
Either of the above queries should work.
replace for persian word
UPDATE dbo.TblNews
SET keyWords = REPLACE(keyWords, '-', N'،')
help:
dbo.TblNews -- table name
keyWords -- fild name

How to split comma separated text in MySQL stored procedure

How to split comma separated text (list of IDs) in MySQL stored procedure to use result in SQL "IN" statement.
SELECT * FROM table WHERE table.id IN (splitStringFunction(commaSeparatedData, ','));
This is simple as hell for MySQL:
SELECT * FROM table WHERE FIND_IN_SET(table.id, commaSeparatedData);
Reference: http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_find-in-set
You could use a prepared statement inside the stored procedure to achieve this. You can create the whole select query as a string inside a variable and then concatenate in the comma delimited string into its IN clause. Then you can make a prepared statement from the query string variable and execute it.
DELIMITER ;;
create procedure testProc(in listString varchar(255))
BEGIN
set #query = concat('select * from testTable where id in (',listString,');');
prepare sql_query from #query;
execute sql_query;
END
;;
DELIMITER ;
call testProc("1,2,3");
You could try this MySql example. Before you use it, put some type safety checks in there (i.e. check id is integer, or match against regular expression before insert).
# BEGIN split statements ids
DECLARE current_pos INT DEFAULT 1;
DECLARE delim CHAR DEFAULT ',';
DECLARE current CHAR DEFAULT '';
DECLARE current_id VARCHAR(100) DEFAULT '';;
CREATE TEMPORARY TABLE ids (`id` VARCHAR(100));
split_ids: LOOP
SET current = MID(statement_ids, current_pos, 1);
IF (current_pos = LENGTH(statement_ids)) THEN
IF current != delim THEN SET current_id = CONCAT(current_id,current); END IF;
INSERT INTO ids(id) VALUES (current_id);
LEAVE split_ids;
END IF;
IF current = delim THEN
INSERT INTO ids(id) VALUES (current_id);
SET current_id = '';
ELSE
SET current_id = CONCAT(current_id,current);
END IF;
SET current_pos = current_pos+1;
END LOOP split_ids;
# END split statement ids
# to check ids are correct
SELECT * FROM ids;
# to use the ids:
SELECT * FROM statements WHERE id IN (SELECT id FROM ids);
OK, slightly "easier" but less geeky way for people like me:
say you have one table 'combined_city_state' which looks like:
'Chicago, Illinois'
copy that to 2 other tables:
CREATE TABLE city LIKE combined_city_state;
INSERT city SELECT * FROM combined_city_state;
CREATE TABLE state LIKE combined_city_state;
INSERT state SELECT * FROM combined_city_state;
You now have 3 tables with the same data as 'combined_city_state'.
Install this function:
CREATE FUNCTION SPLIT_STR(
x VARCHAR(255),
delim VARCHAR(12),
pos INT
)
RETURNS VARCHAR(255)
RETURN REPLACE(SUBSTRING(SUBSTRING_INDEX(x, delim, pos),
LENGTH(SUBSTRING_INDEX(x, delim, pos -1)) + 1),
delim, '');
Then apply this to each table to remove the extra index of data:
UPDATE firms
SET city = (SELECT SPLIT_STR((city), ',', 1));
UPDATE firms
SET state = (SELECT SPLIT_STR((state), ',', 2));
This leaves you with one column of just cities, one of just states. You can now remove the original 'combined_city_state' column if you don't need anymore.
You can do it two ways:
SQL Library
Natively with REGEXP
I'm surprised this one-liner isn't properly mentioned here:
SELECT * FROM table
WHERE id in (SELECT convert(int,Value) FROM dbo.Split(#list_string,',')
All you need is a Split SQL function like the one below which will come in handy in other ways as well:
CREATE FUNCTION dbo.Split
(
#List nvarchar(2000),
#SplitOn nvarchar(5)
)
RETURNS #RtnValue table
(
Id int identity(1,1),
Value nvarchar(100)
)
AS
BEGIN
While (Charindex(#SplitOn,#List)>0)
Begin
Insert Into #RtnValue (value)
Select
Value = ltrim(rtrim(Substring(#List,1,Charindex(#SplitOn,#List)-1)))
Set #List = Substring(#List,Charindex(#SplitOn,#List)+len(#SplitOn),len(#List))
End
Insert Into #RtnValue (Value)
Select Value = ltrim(rtrim(#List))
Return
END
You can use find_in_set() function for collection filter
how-to-split-and-search-in-comma-separated-values-in-mysql
SELECT * FROM table WHERE find_in_set(table.id,commaSeparatedData) > 0;
I have parsed data with hyphens in it. The example below uses a fixed text string to demonstrate, just change the references to relevant column names in the table. I played for ages with a way to ensure it worked on codes with varying numbers of components and in the end decided to add the where clause. Most data you are trying to parse would have a fixed number of columns.
select
SUBSTRING_INDEX(TS,"-",1) as "1",
reverse(left(reverse(SUBSTRING_INDEX(TS,"-",2)),locate("-",reverse(SUBSTRING_INDEX(TS,"-",2)))-1)) as "2",
reverse(left(reverse(SUBSTRING_INDEX(TS,"-",3)),locate("-",reverse(SUBSTRING_INDEX(TS,"-",3)))-1)) as "3",
reverse(left(reverse(SUBSTRING_INDEX(TS,"-",4)),locate("-",reverse(SUBSTRING_INDEX(TS,"-",4)))-1)) as "4",
reverse(left(reverse(SUBSTRING_INDEX(TS,"-",5)),locate("-",reverse(SUBSTRING_INDEX(TS,"-",5)))-1)) as "5",
reverse(left(reverse(SUBSTRING_INDEX(TS,"-",6)),locate("-",reverse(SUBSTRING_INDEX(TS,"-",6)))-1)) as "6",reverse(left(reverse(SUBSTRING_INDEX(TS,"-",7)),locate("-",reverse(SUBSTRING_INDEX(TS,"-",7)))-1)) as "7",
reverse(left(reverse(SUBSTRING_INDEX(TS,"-",8)),locate("-",reverse(SUBSTRING_INDEX(TS,"-",8)))-1)) as "8",
reverse(left(reverse(SUBSTRING_INDEX(TS,"-",9)),locate("-",reverse(SUBSTRING_INDEX(TS,"-",9)))-1)) as "9",
reverse(left(reverse(SUBSTRING_INDEX(TS,"-",10)),locate("-",reverse(SUBSTRING_INDEX(TS,"-",10)))-1)) as "10"
from (select "aaa-bbb-ccc-ddd-eee-fff-ggg-hhh-iii-jjj" as TS) as S
where (LENGTH(TS)-LENGTH(REPLACE(TS,'-',''))) =9
A bit strange but:
SET #i = 1;
set #str = 'a,b,c,d,e,f,g,h';
select temp.length into #length from
(select
ROUND(
(
LENGTH(dt.data)
- LENGTH( REPLACE (dt.data, ",", "") )
) / LENGTH(",")
)+1 AS length
from (select #str as data) dt
) temp;
SET #query = CONCAT('select substring_index(
substring_index(#str, '','', seq),
'','',
-1
) as letter from seq_', #i, '_to_',#length);
PREPARE q FROM #query;
EXECUTE q;