Question:
What's the best way to 'extract' all Rows where the TEXT column contains a 7 digit number starting with 7 and only show the 7 digit number?
SQL Server 2017:
CREATE TABLE [TABLE_1] (
TEXT varchar(50) Null,
);
INSERT INTO TABLE_1
(TEXT)
VALUES
('7005011'),
('The Number is 7335022'),
('asd*.-: wqe'),
('/7225033/.123'),
('Nr.: 7115044')
;
SQL Fiddle Link
The desired result would be:
+---------+
| TEXT |
+---------+
| 7005011 |
| 7335022 |
| 7225033 |
| 7115044 |
+---------+
There's no RegEx in SQL Server natively, you need to use PATINDEX, SUBSTRING, and LIKE:
SELECT [TEXT] = SUBSTRING([TEXT],
PATINDEX('%7' + REPLICATE('[0-9]', 6) + '%', [TEXT]), 7)
FROM dbo.TABLE_1
WHERE [TEXT] LIKE '%7' + REPLICATE('[0-9]', 6) + '%';
Output:
TEXT
7005011
7335022
7225033
7115044
Example db<>fiddle
Related
So I have this Openquery in a stored procedure, where I need to return results where the values in a column are the same as the ones in a local table
exec spx_SELECT_LocalizacoesEtiquetas
GO
IF OBJECT_ID('dbo.spx_SELECT_LocalizacoesEtiquetas') IS NOT NULL
DROP PROCEDURE spx_SELECT_LocalizacoesEtiquetas
GO
CREATE PROCEDURE spx_SELECT_LocalizacoesEtiquetas
AS
BEGIN
SET NOCOUNT ON
DECLARE #SQL NVARCHAR(MAX);
SET #SQL =
'SELECT ET0109 AS Localizacao, Etiquetas
FROM OpenQuery(MACPAC, ''SELECT FET001.ET0109, FET001.ET0101 AS Etiquetas
FROM AUTO.D805DATPOR.FET001 FET001
WHERE FET001.ET0104=''''POE'''' AND FET001.ET0105=''''DIS'''''' AND FET001.ET0101 = '''''
+ (SELECT Localizacao FROM xLocalizacao WHERE InventarioID = 1 ) + ''''' ) ';
EXEC sp_executesql #SQL
END
basically it won't accept the subquery 'cause it says it has too many values.... So my question is. How can i limit the values from the subquery where the values of a column match the ones in a local table? basically a where column A in open query = column B in local table
EDIT.
Here is what I'm trying to achieve.
SubQuery returns from Local table
Column A
| A |
| B |
| C |
| D |
| E |
Open query returns
Column A Column B
| A | 0 |
| A | 0 |
| A1 | 1 |
| A | 2 |
| B | 3 |
| B | 3 |
| B1 | 4 |
Final result should Be
Final query
Column A Column B
| A | 0 |
| A | 0 |
| A | 2 |
| B | 3 |
| B | 3 |
Ok, there are two changes you need to make in your approach.
First of all, you are concatenating your sub-query to a string. No matter what, your subquery has to return a single value, not a multi-row set. So you need to use the method of your choice for having your query return a comma-separated string.
Here's one that will work on any version of SQL Server after 2005.
in other words, instead of this:
Column A
| A |
| B |
| C |
| D |
| E |
your subquery needs to return a single varchar column containing this:
'A','B','C','D','E'
The next change you need to make is using IN instead of =.
So instead of this:
AND FET001.ET0101 = '''''
+ (Your Subquery) + ''''' ) '
you need this:
AND FET001.ET0101 IN ( '
+ (Your Subquery) + ') ) '
My script looks like this :
SELECT
regexp_replace(column1,'"resId":([^"]+?)..','"resId":column2,"')
FROM
table;
Here, I need to replace resId value in column1 by value from column2.
It is hard to tell without the sample data and expected output what you exactly want.
It appears you are expecting to transform a pattern like this - "resId":Value1,"otherid":othervalue
Please note I took into consideration that a key value pair of
"resID":value exists in the data and there is a separator ( a space or a comma) between such key-value pairs.
(,|$) indicates a comma separator or end of line after the value. You may change this to contain any separator in your data that distinguishes it from other combinations. If there is no such thing and the data is purer than this, you should care to describe it clearly by editing your question, which may help us to provide you a proper solution.
SQL Fiddle
Query:
SELECT column1,
column2,
regexp_replace(column1,'"resId":[^"]+(,|$)','"resId":' || column2 || '\1') as replaced
FROM t
Results:
| COLUMN1 | COLUMN2 | REPLACED |
|-------------------------------------|---------|-------------------------------------|
| "resId":Value1,"otherid":othervalue | Value2 | "resId":Value2,"otherid":othervalue |
| "otherid":othervalue,"resId":Value1 | Value2 | "otherid":othervalue,"resId":Value2 |
Concatenate the column2 value into your replacement string:
SELECT regexp_replace(
column1,
'"resId":([^"]+?),"','"resId":' || column2 || ',"'
)
FROM table;
However, if you data is well-formed JSON and the "resId" value will be a simple literal (not an array or an object) then you can use a regular expression that would parse this like:
'("resId":)(null|true|false|(-?0|[1-9]\d*)(\.\d*)?([eE][+-]?\d+)?|"(\\["\/bfrnt]|\\u\d{4}|[^"\/'||CHR(8)||CHR(9)|| CHR(10)||CHR(12)||CHR(13)||'])*")'
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE table_name ( column1, column2 ) AS
SELECT '{"resId":null}', 1 FROM DUAL UNION ALL
SELECT '{"resId":true}', 2 FROM DUAL UNION ALL
SELECT '{"resId":false}', 3 FROM DUAL UNION ALL
SELECT '{"resId":123}', 4 FROM DUAL UNION ALL
SELECT '{"resId":""}', 5 FROM DUAL UNION ALL
SELECT '{"resId":"\r\n"}', 6 FROM DUAL UNION ALL
SELECT '{"resId":"test"}', 7 FROM DUAL UNION ALL
SELECT '{"resId":"' || CHR(13) || CHR(10) || '"}', 8 FROM DUAL;
Query 1:
SELECT column1,
column2,
regexp_replace(
column1,
'("resId":)(null|true|false|(-?0|[1-9]\d*)(\.\d*)?([eE][+-]?\d+)?|"(\\["\/bfrnt]|\\u\d{4}|[^"\/'||CHR(8)||CHR(9)|| CHR(10)||CHR(12)||CHR(13)||'])*")',
'\1' || column2
) As repl
FROM table_name
Results:
| COLUMN1 | COLUMN2 | REPL |
|------------------|---------|----------------|
| {"resId":null} | 1 | {"resId":1} |
| {"resId":true} | 2 | {"resId":2} |
| {"resId":false} | 3 | {"resId":3} |
| {"resId":123} | 4 | {"resId":4} |
| {"resId":""} | 5 | {"resId":5} |
| {"resId":"\r\n"} | 6 | {"resId":6} |
| {"resId":"test"} | 7 | {"resId":7} |
| {"resId":" | 8 | {"resId":" | -- Note: not well-formed JSON
| "} | | "} | -- so did not get matched.
I am using SQL Server 2008.
I have a varchar(30) column which holds check numbers. If the payment was made using a credit card, checknbr will be a zero-length string. I need to pad this data with leading zeroes such that the entire output is ten digits long. If there is no check number, it should just be ten zeroes.
Here is the data I would like to see:
0000000000
0000000000
0000000114
0000000105
0000000007
Here is the query I have been using and am stuck on:
SELECT RIGHT((CASE
WHEN LEN(checknbr) = 0 THEN '0000000000'
ELSE '0000000000'+checknbr
END),10) as checknbr
FROM payhistory
WHERE number = 12345678
And this is what I get:
0000000000
0000000000
114
105
7
Trying another way:
SELECT RIGHT('0000000000'+checknbr,10)
FROM payhistory
WHERE number = 3861821
And I get the same results. Oddly enough, I have a varchar(10) column where
RIGHT('0000'+EDC.DatabaseNumber,4)
yields exactly the results I am after. What am I missing here? Something about a quirk with the RIGHT function?
Thanks in advance
If you are using SQL server 2012 or up try the following:
SELECT RIGHT(CONCAT('0000000000', checknbr), 10)
Concat will automatically convert NULL values to empty strings, removing the need for extra checks.
By the way, the issue you're having is the fact that your query still sees checknbr as a number instead of a varchar value. Casting it to varchar will solve that for you.
EDIT SQL Server 2008:
Since you have a VARCHAR column with no NULL values the only thing that still comes to mind are trailing spaces. Try:
SELECT RIGHT('0000000000' + RTRIM(checknbr), 10);
using cast() or convert() to convert checknbr to a character value will solve the implicit conversion of '0000000000' to the integer 0.
select right('0000000000'+convert(varchar(10),checknbr),10)
from payhistory
where number = 3861821
If checknbr can be null and you want it to return as '0000000000', then you can wrap it in coalesce() or isnull():
select right('0000000000'+isnull(convert(varchar(10),checknbr),''),10)
from payhistory
where number = 3861821
If checknbr is not a number, but varchar(30), then (as Jens points out), you may have padded spaces that need to be trimmed:
rextester demo: http://rextester.com/IRLV83801
create table payhistory (checknbr varchar(30));
insert into payhistory values ('0'), ('1'), (' 0'), ('0 '),(' ');
select checknbr = right('0000000000'+checknbr,10)
from payhistory
returns:
+------------+
| checknbr |
+------------+
| 0000000000 |
| 0000000001 |
| 0 |
| 0 |
| |
+------------+
And if you trim the padded spaces:
select checknbr = right('0000000000'+ltrim(rtrim(checknbr)),10)
from payhistory
returns:
+------------+
| checknbr |
+------------+
| 0000000000 |
| 0000000001 |
| 0000000000 |
| 0000000000 |
| 0000000000 |
+------------+
I have a table structured as such:
| ID | Name |
| 1 | Bob |
| 2 | Jim |
| 3 | Jane |
. .
. .
. .
I am trying to compose a query that will return all ID's of the names that I will be passing. Note that the names will be passed as a comma delimited string.
The query i've tried is:
#Names = 'Bob, Jane'
select ID into #Ids from Users where Name in ((select i.Item from dbo.Split(#Names, ',', 0) as i))
What I was hoping to get was:
| ID |
| 1 |
| 3 |
but instead I just get:
| ID |
| 1 |
I would have to loop through this query, but what is the best way to do so? Am I approaching this problem correctly?
The problem might be the trailing spaces in the output of split function.
After comma you have a space. It should be removed because in SQL Server only = operator ignores trailing spaces when making the comparison. Use Ltrim and Rtrim functions to remove the trailing spaces before making comparison
SELECT ID
INTO #Ids
FROM Users
WHERE NAME IN ((SELECT rtrim(ltrim(i.Item))
FROM dbo.Split(#Names, ',', 0) AS i))
I have Letters table:
+--------------+-------+
| SerialNumber | Letter|
+--------------+-------+
| 1 | A |
| 2 | B |
| 3 | C |
| 4 | D |
+--------------+-------+
How to write TSQL insert stored procedure PA_Letters_INS which automatically adds max of previous serial number values and has letter insert parameter (without MSSQL autoincrement functionality on SerialNumber column).
(exec PA_Letters_INS 'E' adds {5, E} record)
#Letter being you Stored Procedure Parameter,
INSERT INTO Letters(SerialNumber, Letter)
SELECT MAX(SerialNumber) + 1, #Letter
FROM Letters