How to add '' and , for multiple ID in SQL Server - sql

I am writing a SELECT query that has multiple id, and I have to manually add '','' (e.g '12L','22C').
I have around 2000 id in an Excel sheet.
Is there any quicker way to add '','' to all the ID?
SELECT id, name
FROM table
WHERE id IN ('12L', '22C', 33j, 7k, 44J, 234C)

DECLARE #Ids VARCHAR(MAX) = '12L,22C,33j,7k,44J,234C'
--Your question's answer.
DECLARE #Splitted VARCHAR(MAX) = STUFF((
SELECT CONCAT(',''', value, '''')
FROM string_split(#Ids, ',')
FOR XML PATH('')), 1, 1, '')
SELECT #Splitted
--'12L','22C','33j','7k','44J','234C'
OR simplified
SELECT id, name from table where id in (SELECT value FROM string_split(#Ids, ','))
string_split: for more information docs
concat: for more information docs

Here is a conceptual example for you. It will work in SQL Server 2012 onwards.
It is a three step process:
Convert input string into XML.
Convert XML into a relational resultset inside the CTE.
Join with a DB table.
SQL
-- DDL and sample data population, start
DECLARE #tbl TABLE (ID INT IDENTITY PRIMARY KEY, Code VARCHAR(10), City VARCHAR(50));
INSERT INTO #tbl (Code, City) VALUES
('10T', 'Miami'),
('45L', 'Orlando'),
('50Z', 'Dallas'),
('70W', 'Houston');
-- DDL and sample data population, end
DECLARE #Str VARCHAR(100) = '22C,45L,50Z,105M'
, #separator CHAR(1) = ',';
DECLARE #parameter XML = TRY_CAST('<root><r><![CDATA[' +
REPLACE(#Str, #separator, ']]></r><r><![CDATA[') +
']]></r></root>' AS XML);
;WITH rs AS
(
SELECT c.value('.', 'VARCHAR(10)') AS Code
FROM #parameter.nodes('/root/r/text()') AS t(c)
)
SELECT t.*
FROM #tbl AS t INNER JOIN
rs ON t.Code = rs.Code;

Two alternatives if you're ok doing the transformation outside of SQL.
As one of the comments on your question suggests, you could do this in Excel using this as a formula:
="'" & A1 & "',"
Replace the "A1" with whatever cell your first ID is in. After you enter the formula, click the cell it's in, and there will be a small square on the bottom right. Double click that and it will apply the formula to every cell in the column, automatically shifting the cell reference to match the current row. You can then copy the values from that column and erase the comma at the end.
You could also use an editor that supports regular expression like SSMS, Azure Data Studio, Notepad++, etc and do a Find+Replace:
Paste your IDs in
Hit the replace hotkey (Ctrl+H in all 3 of the ones I listed). There will be an option to enable Regular Expression (SSMS/ADS have a little .* icon, Notepad++ has a labeled radio button). Click it
Find this:
(\w+)
Replace it with this
'$1',
Copy and paste the formatted IDs into your query. Same as above, you'll have to erase the final comma
This will work as long as your IDs are alphanumeric with no spaces, punctuation, etc. If the formatting is more complex, the regex (the (\w+) you search for) will need to be more complex as well. Using this strategy, you could also get rid of the linebreaks by using the regex (\w+)\r\n.

hei, you can use Function CONCATENATE in Excel before you copy those ID in sql.

Related

Increase SQL column max size from nvarchar (max) up to 300 thousand

I am trying to insert huge content in the format of JSON in a table column.
At the moment it throws no error however when displaying the data in the column, it only prints half of the entered details.
How can I increase the length of nvarchar(max) to nvarchar(300,000).
At the moment, I'm using SQL Server 15.0 version therefore I cannot use JSON data type.
I would appreciate any help on this.
For the display issue, there used to be a handy "bug" in the results grid, in SSMS, swapping the position of an XML column and clicking on it, would display the contents of the column (left or right) of the XML*(this depends on the initial position of the xml in the resultset)
declare #json nvarchar(max) = concat('["a"', replicate(cast(concat(',"', newid(), '"') as nvarchar(max)), 10000), ']');
select isjson(#json) as _isjson, len(#json) as _len;
select
'<![CDATA[content start-->'+ #json + ' <-- content end]]>' as colA,
cast('drag me to the left of colA and click me' as xml) as b;
CDATA is not actually needed if colA does not contain any breaking & illegal XML characters.
declare #longchar nvarchar(max) = concat('"a"', replicate(cast(concat(',"', newid(), '"') as nvarchar(max)), 10000));
select
#longchar as colA,
cast('drag me to the left of cola and click me' as xml) as b;

Replace string without fixed length

I have some data that I'm looking at that has text formatting stored within a NTEXT field.
Happy enough with SQL Replace to remove data of a known length and format, however there are some fields with what looks like colour formatting and I'm trying to find a way to remove these.
An example of the data below, however (if possible) I would like to be able to remove whatever numbers follow the colours in the data but can't see how to introduce a wildcard into the replace statement.
Something like '\red***\green\***\blue***' as per Excel, but this doesn't work in Sql Server.
declare #str varchar(1500) = '\red3\green73\blue125;Jimmy Jazz\red31\green73\blue125;'
select #str,
replace(#str,'\red31\green73\blue125;','')
Any pointers would be gratefully received, thanks in advance.
Based on your sample data it would appear that you only need to remove the numbers in your string you can use patreplace8k or using patextract8K. Note the sample data and examples below:
-- Sample data
DECLARE #strings TABLE(stringId INT IDENTITY, string VARCHAR(100));
INSERT #strings VALUES('DeepPurple1978\yellow2\red009;pink\black3322'),
('red202\yellow5\red009;hotpink2'),('purple999\gray65\violet;blue\yellow381');
--==== Solution #1 Patreplace8k
SELECT
s.stringId,
pr.newString
FROM #strings AS s
CROSS APPLY samd.patReplace8K(s.string,'[0-9]','') AS pr;
--==== Solution #2 PatExtract8k + STRING_AGG (SQL 2017+)
SELECT
s.stringId,
NewString = STRING_AGG(pe.Item,'') WITHIN GROUP (ORDER BY pe.ItemNumber)
FROM #strings AS s
CROSS APPLY samd.patExtract8K(s.string,'[0-9]') AS pe
GROUP BY s.stringId;
--==== Solution #3 PatExtract8k + XML Concatination (Pre SQL 2017\)
SELECT
s.stringId,
NewString =
(
SELECT pe.item+''
FROM #strings AS s2
CROSS APPLY samd.patExtract8K(s2.string,'[0-9]') AS pe
WHERE s.stringId = s2.stringid
ORDER BY pe.itemNumber
FOR XML PATH('')
)
FROM #strings AS s
GROUP BY s.stringId;
Each of these solutions return:
stringId NewString
----------- -------------------------------------
1 DeepPurple\yellow\red;pink\black
2 red\yellow\red;hotpink
3 purple\gray\violet;blue\yellow
The second and third leverage concatenation, the second compatible with SQL Server 2017+ the third works with earlier versions (you did not include what version you are on.)
To only strip the numbers that follow one or more pre-defined colors you could use patternsplitCM. Note the use of a table with a group of colors your are seeking; in the real world I'd use a real table.
-- Colors
DECLARE #colors TABLE(color VARCHAR(20) PRIMARY KEY);
INSERT #colors VALUES('red'),('green'),('blue'),('yellow'),('purple'),('grey');
-- Sample data
DECLARE #strings TABLE(stringId INT IDENTITY, string VARCHAR(100));
INSERT #strings VALUES('Burger1978\yellow2\red009;pink\86thisfool'),
('red202\yellow5\red009;Freddy99'),('green999\grey65\violet;blue\yellow381');
SELECT
s.stringId, s.string, NewString =
(
SELECT
(
SELECT SUBSTRING(f.Item, IIF(f.M=0 AND EXISTS (SELECT c.Color FROM #colors AS c
WHERE c.Color = f.L),NULLIF(PATINDEX('%[^0-9]',f.item),0),1),8000)
FROM
(
SELECT ps.ItemNumber, ps.Item, ps.[Matched],
LAG(ps.Item,1,ps.Item) OVER (ORDER BY ps.ItemNumber)
FROM dbo.PatternSplitCM(s.string,'[^0-9\ ;]') AS ps
) AS f(ItemNumber,Item,M,L)
ORDER BY f.ItemNumber
FOR XML PATH(''), TYPE
).value('(text())[1]','varchar(8000)')
)
FROM #strings AS s;
Returns:
stringId string NewString
----------- --------------------------------------------- ----------------------------------------
1 Burger1978\yellow2\red009;pink\86thisfool Burger1978\yellow\red;pink\86thisfool
2 red202\yellow5\red009;Freddy99 red\yellow\red;Freddy99
3 green999\grey65\violet;blue\yellow381 green\grey\violet;blue\yellow

split string from a string by sql

I have this type of data in a column in my table,,,
QCIM1J77477, 4650125572, QCCR1J77891, 4650312729, QCCR1J74974 --- remove without comma
or
QCIM1E107498,QCIM1E109835,4650092399/ QCCR1E91190, -- remove 4650092399
I want only that string which starts from QC,remove apart from QC,
so please tell me how can I achive it?
Beneath a piece of t-sql script that creates a temporary table #t with temporary variables. Here the temporary table exists untill you break your session, temporary variables exist during the execution of the script. I have a drop table statement at the bottom. Figure out yourself what you want with the table data and whether you want the data put in somewhere else, for example in a not-temporary table :).
I assume you want all the pieces of the string that contain 'QC' as seperate values. If you want your data back as it was originally, that is multiple strings per one column, then you could also do a group by trick. Then you do need a unique identifier of some sort, like name, id, guid of each row or identity.
create table #t ([QCs] nvarchar(100))
declare #str nvarchar(500)
set #str = 'QCIM1E107498,QCIM1E109835,4650092399/ QCCR1E91190'
--replace the above temporary variable with the column you are selecting
declare #sql nvarchar(4000)
select #sql = 'insert into #t select '''+ replace(#str,',',''' union all select ''') + ''''
print #sql
exec ( #sql )
select
QCs
,PATINDEX('%QC%',QCs) as StartPosition
,SUBSTRING(QCs,PATINDEX('%QC%',QCs),12) as QCsNew
from #t where QCs like '%QC%'
drop table #t
With PATINDEX you find the position where in the string 'QC' starts, and with SUBSTRING you tell the dbms to give back (here) 12 characters starting from the found StartPosition.
Beneath what the result looks like. QCsNew is your desired result.
QCs StartPosition QCsNew
QCIM1E107498 1 QCIM1E107498
QCIM1E109835 1 QCIM1E109835
4650092399/ QCCR1E91190 13 QCCR1E91190

How to get the data between mth and nth occurrence in a string

I'm using a SQL Server query to fetch the column information. But I need some information which is after 3rd and 4th occurrence in that particular column
Here is my sample data
[xxxxxxx||gh||vbh||CAPACITY_CPU||aed]
[qwe34||asdf||qwe||CONNECTIVITY||ghj]
[ertgfy||fgv||yuhjj||ACCESS||rty]
[tyhuj||rtg||qwert||ACCESS||TMW]
I'm looking for the data information after 3rd and 4th occurrence of ||
Something like
Capacity_CPU
CONNECTIVITY
ACCESS
My source column is not specific length, it will vary in the length
Use PATINDEX
create regex for the column that you need, then use SUBSTRING to extract the string that you want
You can use mixture of SUBSTRING, CHARINDEX, LEFT AND RIGHT Function. The best solution is you have to play with this function.
`
Create table #t( Name varchar(200))
Insert into #t
values
('[xxxxxxx||gh||vbh||CAPACITY_CPU||aed]'),
('[qwe34||asdf||qwe||CONNECTIVITY||ghj]'),
('[ertgfy||fgv||yuhjj||ACCESS||rty]'),
('[tyhuj||rtg||qwert||ACCESS||TMW]')
Select * from #t
Select
name,
Right(LEFT(name,len(name)-6),charindex('||',reverse(LEFT(name,len(name)-7))))
From #t
`
1) Instead of trying to do such operations with those strings you could normalize database by designing and adding a new table. In this case, you would need a simple SELECT:
SELECT Column4
FROM dbo.Table;
2) Otherwise, one solution is to convert those strings into XML and to use nodes and value XML methods:
DECLARE #Source NVARCHAR(MAX);
SET #Source =
N'[xxxxxxx||gh||vbh||CAPACITY_CPU||aed]
[qwe34||asdf||qwe||CONNECTIVITY||ghj]
[ertgfy||fgv||yuhjj||ACCESS||rty]
[tyhuj||rtg||qwert||ACCESS||TMW]';
DECLARE #EncodedSource NVARCHAR(MAX);
SET #EncodedSource = (SELECT #source FOR XML PATH(''));
DECLARE #x XML;
SET #x = REPLACE(REPLACE(REPLACE(#EncodedSource, N'[', N'<row> <col>'), N']', N'"</col> </row>'), N'||', N'</col> <col>');
SELECT r.XmlContent.value('(col[1]/text())[1]', 'NVARCHAR(100)') AS Col1,
r.XmlContent.value('(col[4]/text())[1]', 'NVARCHAR(100)') AS Col4
FROM #x.nodes('/row') r(XmlContent);
Note: you need to replace NVARCHAR(length) with the proper data type and max. length.

String manipulation SQL

I have a row of strings that are in the following format:
'Order was assigned to lastname,firsname'
I need to cut this string down into just the last and first name but it is always a different name for each record.
The 'Order was assigned to' part is always the same.......
Thanks
I am using SQL Server. It is multiple records with different names in each record.
In your specific case you can use something like:
SELECT SUBSTRING(str, 23) FROM table
However, this is not very scalable, should the format of your strings ever change.
If you are using an Oracle database, you would want to use SUBSTR instead.
Edit:
For databases where the third parameter is not optional, you could use SUBSTRING(str, 23, LEN(str))
Somebody would have to test to see if this is better or worse than subtraction, as in Martin Smith's solution but gives you the same result in the end.
In addition to the SUBSTRING methods, you could also use a REPLACE function. I don't know which would have better performance over millions of rows, although I suspect that it would be the SUBSTRING - especially if you were working with CHAR instead of VARCHAR.
SELECT REPLACE(my_column, 'Order was assigned to ', '')
For SQL Server
WITH testData AS
(
SELECT 'Order was assigned to lastname,firsname' as Col1 UNION ALL
SELECT 'Order was assigned to Bloggs, Jo' as Col1
)
SELECT SUBSTRING(Col1,23,LEN(Col1)-22) AS Name
from testData
Returns
Name
---------------------------------------
lastname,firsname
Bloggs, Jo
on MS SQL Server:
declare #str varchar(100) = 'Order was assigned to lastname,firsname'
declare #strLen1 int = DATALENGTH('Order was assigned to ')
declare #strLen2 int = len(#str)
select #strlen1, #strLen2, substring(#str,#strLen1,#strLen2),
RIGHT(#str, #strlen2-#strlen1)
I would require that a colon or some other delimiter be between the message and the name.
Then you could just search for the index of that character and know that anything after it was the data you need...
Example with format changing over time:
CREATE TABLE #Temp (OrderInfo NVARCHAR(MAX))
INSERT INTO #Temp VALUES ('Order was assigned to :Smith,Mary')
INSERT INTO #Temp VALUES ('Order was assigned to :Holmes,Larry')
INSERT INTO #Temp VALUES ('New Format over time :LootAt,Me')
SELECT SUBSTRING(OrderInfo, CHARINDEX(':',OrderInfo)+1, LEN(OrderInfo))
FROM #Temp
DROP TABLE #Temp