Allow leading zeros in a LIKE statement - sql

I have a SQL query which includes the line:
WHERE
[TraceableItem].[IdentificationNo] LIKE N'015933%'
I would like this to match the following numbers:
015933
00015933
000000000015933
But not allow any non-zero characters. How could I do this?

--Some test data
DECLARE #sample TABLE
(
number_as_string VARCHAR(20)
)
INSERT INTO #sample
VALUES
('015933') -- okay
,('00015933') -- okay
,('000000000015933')-- okay
,(' 00015933') -- dont return as this doesnt start with a 0
,('25') -- dont return wrong number
,('string') -- dont return as its a string
,('st15933') -- dont return as it starts with a string.
,('001000015933') -- dont return as this is the number 1000015933
SELECT
*
FROM
#sample as s
WHERE
--only consider rows that are a number
--stops CONVERT exception being thrown on lines that do no convert
ISNUMERIC(s.number_as_string) = 1
AND
--Convert to INT wipes out the leading 0's, but also spaces
CONVERT(INT,s.number_as_string) LIKE '15933%'
AND
--must start with a number, i.e. check it doesn't start with a space.
--LEFT(s.number_as_string,1) NOT LIKE '[^0-9]'
--This version is easier to read as its not a double NOT logic like the version above
--Thanks to #Robert Kock
LEFT(s.number_as_string,1) BETWEEN '0' AND '9'
Gives the result
number_as_string
----------------
015933
00015933
000000000015933

You probably want to first convert to int and back to string as suggested by Neeraj Agarwal. But then take the left five characters and compare for exact equality to '15933'
where '15933' = left(convert(varchar(50),convert(int,
TraceableItem.IdentificationNo
)),5)
You can see it at work in the sample below, where it captures everything you desire and a little more, but doesn't capture the case presented by Harry Adams in the comments to Neeraj.
select *
from (values
('015933'),
('00015933'),
('000000000015933'),
('0001593399'),
('15933'),
('001000015933')
) vals (v)
where '15933' = left(convert(varchar(50),convert(int, v)),5)

I don't like converting to a number for this purpose. But one method is to "trim" the leading zeros away. For an exact match:
where replace(ltrim(replace([TraceableItem].[IdentificationNo], '0', ' ')), ' ', '0') = '15933'
For LIKE:
where replace(ltrim(replace([TraceableItem].[IdentificationNo], '0', ' ')), ' ', '0') LIKE '15933%'
You can also express this with LIKE/NOT LIKE:
where TraceableItem].[IdentificationNo] like '%15933%' and
TraceableItem].[IdentificationNo] not like '%[^0]%15933%'

You can use cast to convert to an int and back to a character string provided the string consists of digits only, e.g.:
select cast(cast("00015933" as int) as varchar(24))

Related

In SQL Server, how can I search for column with 1 or 2 whitespace characters?

So I need to filter column which contains either one, two or three whitespace character.
CREATE TABLE a
(
[col] [char](3) NULL,
)
and some inserts like
INSERT INTO a VALUES (' ',' ', ' ')
How do I get only the row with one white space?
Simply writing
SELECT *
FROM a
WHERE column = ' '
returns all rows irrespective of one or more whitespace character.
Is there a way to escape the space? Or search for specific number of whitespaces in column? Regex?
Use like clause - eg where column like '%[ ]%'
the brackets are important, like clauses provide a very limited version of regex. If its not enough, you can add a regex function written in C# to the DB and use that to check each row, but it won't be indexed and thus will be very slow.
The other alternative, if you need speed, is to look into full text search indexes.
Here is one approach you can take:
DECLARE #data table ( txt varchar(50), val varchar(50) );
INSERT INTO #data VALUES ( 'One Space', ' ' ), ( 'Two Spaces', ' ' ), ( 'Three Spaces', ' ' );
;WITH cte AS (
SELECT
txt,
DATALENGTH ( val ) - ( DATALENGTH ( REPLACE ( val, ' ', '' ) ) ) AS CharCount
FROM #data
)
SELECT * FROM cte WHERE CharCount = 1;
RETURNS
+-----------+-----------+
| txt | CharCount |
+-----------+-----------+
| One Space | 1 |
+-----------+-----------+
You need to use DATALENGTH as LEN ignores trailing blank spaces, but this is a method I have used before.
NOTE:
This example assumes the use of a varchar column.
Trailing spaces are often ignored in string comparisons in SQL Server. They are treated as significant on the LHS of the LIKE though.
To search for values that are exactly one space you can use
select *
from a
where ' ' LIKE col AND col = ' '
/*The second predicate is required in case col contains % or _ and for index seek*/
Note with your example table all the values will be padded out to three characters with trailing spaces anyway though. You would need a variable length datatype (varchar/nvarchar) to avoid this.
The advantage this has over checking value + DATALENGTH is that it is agnostic to how many bytes per character the string is using (dependant on datatype and collation)
DB Fiddle
How to get only rows with one space?
SELECT *
FROM a
WHERE col LIKE SPACE(1) AND col NOT LIKE SPACE(2)
;
Though this will only work for variable length datatypes.
Thanks guys for answering.
So I converted the char(3) column to varchar(3).
This seemed to work for me. It seems sql server has ansi padding that puts three while space in char(3) column for any empty or single space input. So any search or len or replace will take the padded value.

Replacing empty string in SQL using SELECT

I'm trying to replace empty strings with a value and I can't seem to find the best way to do this.
The issue is that SOME values in the phone_number column are in a format without the numbers. For example ( ) -
I want to replace those empty values with 000-0000. I tried to use the CASE WHEN function but that doesn't seem to address the problem. The COALESCE IFNULL won't work because technically the values aren't NULL just incomplete. I'm thinking perhaps the CASE WHEN function would work if I could figure out how to format the empty values correctly.
Here is an example of the code
SELECT
phone_column,
CASE
WHEN phone_column = '() -'
THEN '000-000'
ELSE SUBSTRING(phone_colum, 6, 8)
END AS Phone
FROM
client_table
ORDER BY
linkid_
declare #test table(ph varchar(20))
insert into #test
select '( ) -'
UNION
select ''
UNION
select '(123)-456-7890'
select case
when replace(ph,'( ) -','')='' then '000-000'
else substring(ph,6,8)
end
from #test
if you want to search in a varchar then use LIKE this would help you in using expressions. For instance, in your case phone_column = '() -' would be phone_column LIKE '() -%' this will match any string that begins with () -. if you do phone_column = '() -' then it will only match the exact same string.
Any how, I'm not sure why you want to take this road, while you can validate the current numbers and try to only store the valid ones, as storing invalid numbers would be useless.
I'll give you an example,
to validate phone numbers, you first take out any existed formats (parentheses, dashes, spaces) then you'll be end up with a whole number with 10 or 7 digits. depends on your way of storing phone numbers. any numbers less than that would be invalid.
To remove the formats :
SELECT REPLACE(REPLACE(REPLACE(REPLACE(Number,'(',''),')',''),'-',''),' ','')
Now you will have only numbers, which will be easier to handle.
Like this :
SELECT
phone_column
FROM (SELECT REPLACE(REPLACE(REPLACE(REPLACE(phone_column,'(',''),')',''),'-',''),' ','') phone_column FROM client_table) D
PS : Some countries phone numbers begins with 0, if your numbers don't
begin with 0, then you would cast the number to BIGINT, which will
remove any leading zeros.
Now, you can use the case to validate the numbers and do whatever you like with them.
SELECT
CASE
WHEN LEN(phone_column) = 10
THEN '(' + SUBSTRING(phone_column,1,3) + ') ' + SUBSTRING(phone_column, 3,3) + '-' + SUBSTRING(phone_column, 6,4)
ELSE '(000) 000-0000'
END Phone
FROM (SELECT REPLACE(REPLACE(REPLACE(REPLACE(phone_column,'(',''),')',''),'-',''),' ','') phone_column FROM client_table) D

SQL Command to replace embedded spaces with another character

I have a relational database with several fixed length character fields. I need to permanently replace all the embedded spaces with another character like - so JOHN DOE would become JOHN-DOE and ITSY BISTSY SPIDER would become ITSY-BISTSY-SPIDER. I can search before hand to make sure there are no strings that would conflict. I just need to be able to print the requested files with no embedded spaces. I would do the replacement in the C code but I want to make sure that there is never a future case where there is a JANE DOE and JANE-DOE in the DB.
By the way I have already made sure that there are no strings with more than one consecutive embedded space or leading spaces only trailing spaces to fill the fixed length fields.
Edit: thanks for all the help!
It looks like when I cut & pasted my question from Word to StackOverflow the trailing spaces got lost so the meaning my question was lost a bit.
I need to replace only the embedded spaces not the trailing spaces!
Note: I am using middle dot to stand in for spaces that don't show well.
Using:
SELECT REPLACE(operator_name, ' ', '-') FROM operator_info ;
the string JOHN·DOE············ became JOHN-DOE------------.
I need JOHN-DOE············.
I am thinking I need to use aliasing and the TRIM command but not sure how.
With whatever REPLACE function is built into your particular database.
MySQL:
http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_replace
Oracle:
http://psoug.org/reference/translate_replace.html
SQLServer:
http://msdn.microsoft.com/en-us/library/ms186862.aspx
Edits below based on your comment.
I've done this in SQLServer syntax so please modify the example as needed. The first example really breaks down what's going on and the second one bunches it all into a single ugly query :D
#output in this case contains your final value.
DECLARE #input VARCHAR (100) = ' some test ';
DECLARE #trimmed VARCHAR (100);
DECLARE #replaced VARCHAR (100);
DECLARE #output VARCHAR (100);
-- Get just the inner text without the preceding / trailing spaces.
SET #trimmed = LTRIM (RTRIM (#input));
-- Replace the spaces *inside* the trimmed text with a dash.
SET #replaced = REPLACE (#trimmed, ' ', '-');
-- Take the original text and replace the trimmed version (with the inner spaces) with the dash version.
SET #output = REPLACE (#input, #trimmed, #replaced);
-- Show each step of the process!
SELECT #input AS INPUT,
#trimmed AS TRIMMED,
#replaced AS REPLACED,
#output AS OUTPUT;
And as a SELECT statement.
DECLARE #inputTable TABLE (Value VARCHAR (100) NOT NULL);
INSERT INTO #inputTable (Value)
VALUES (' some test '),
(' another test ');
SELECT REPLACE (Value,
LTRIM (RTRIM (Value)),
REPLACE (LTRIM (RTRIM (Value)), ' ', '-'))
FROM #inputTable;
If you are using MSSQL:
SELECT REPLACE(field_name,' ','-');
Edit: After the requirement about skipping the trailing spaces.
You can try this one-liner:
SELECT REPLACE(RTRIM(#name), ' ', '-') + SUBSTRING(#name, LEN(RTRIM(#name)) + 1, LEN(#NAME))
However I would recommend that you put it into a user defined function instead.
assuming SQL Server:
update TABLE set column = replace (column, ' ','-')
SELECT REPLACE(field_name,' ','-');
Edit: After the requirement about skipping the trailing spaces. You can try this one-liner:
SELECT REPLACE(RTRIM(#name), ' ', '-') + SUBSTRING(#name, LEN(RTRIM(#name)) + 1;

Remove leading zeros

Given data in a column which look like this:
00001 00
00026 00
I need to use SQL to remove anything after the space and all leading zeros from the values so that the final output will be:
1
26
How can I best do this?
Btw I'm using DB2
This was tested on DB2 for Linux/Unix/Windows and z/OS.
You can use the LOCATE() function in DB2 to find the character position of the first space in a string, and then send that to SUBSTR() as the end location (minus one) to get only the first number of the string. Casting to INT will get rid of the leading zeros, but if you need it in string form, you can CAST again to CHAR.
SELECT CAST(SUBSTR(col, 1, LOCATE(' ', col) - 1) AS INT)
FROM tab
In DB2 (Express-C 9.7.5) you can use the SQL standard TRIM() function:
db2 => CREATE TABLE tbl (vc VARCHAR(64))
DB20000I The SQL command completed successfully.
db2 => INSERT INTO tbl (vc) VALUES ('00001 00'), ('00026 00')
DB20000I The SQL command completed successfully.
db2 => SELECT TRIM(TRIM('0' FROM vc)) AS trimmed FROM tbl
TRIMMED
----------------------------------------------------------------
1
26
2 record(s) selected.
The inner TRIM() removes leading and trailing zero characters, while the outer trim removes spaces.
This worked for me on the AS400 DB2.
The "L" stands for Leading.
You can also use "T" for Trailing.
I am assuming the field type is currently VARCHAR, do you need to store things other than INTs?
If the field type was INT, they would be removed automatically.
Alternatively, to select the values:
SELECT (CAST(CAST Col1 AS int) AS varchar) AS Col1
I found this thread for some reason and find it odd that no one actually answered the question. It seems that the goal is to return a left adjusted field:
SELECT
TRIM(L '0' FROM SUBSTR(trim(col) || ' ',1,LOCATE(' ',trim(col) || ' ') - 1))
FROM tab
One option is implicit casting: SELECT SUBSTR(column, 1, 5) + 0 AS column_as_number ...
That assumes that the structure is nnnnn nn, ie exactly 5 characters, a space and two more characters.
Explicit casting, ie SUBSTR(column,1,5)::INT is also a possibility, but exact syntax depends on the RDBMS in question.
Use the following to achieve this when the space location is variable, or even when it's fixed and you want to make a more robust query (in case it moves later):
SELECT CAST(SUBSTR(LTRIM('00123 45'), 1, CASE WHEN LOCATE(' ', LTRIM('00123 45')) <= 1 THEN LEN('00123 45') ELSE LOCATE(' ', LTRIM('00123 45')) - 1 END) AS BIGINT)
If you know the column will always contain a blank space after the start:
SELECT CAST(LOCATE(LTRIM('00123 45'), 1, LOCATE(' ', LTRIM('00123 45')) - 1) AS BIGINT)
both of these result in:
123
so your query would
SELECT CAST(SUBSTR(LTRIM(myCol1), 1, CASE WHEN LOCATE(' ', LTRIM(myCol1)) <= 1 THEN LEN(myCol1) ELSE LOCATE(' ', LTRIM(myCol1)) - 1 END) AS BIGINT)
FROM myTable1
This removes any content after the first space character (ignoring leading spaces), and then converts the remainder to a 64bit integer which will then remove all leading zeroes.
If you want to keep all the numbers and just remove the leading zeroes and any spaces you can use:
SELECT CAST(REPLACE('00123 45', ' ', '') AS BIGINT)
While my answer might seem quite verbose compared to simply SELECT CAST(SUBSTR(myCol1, 1, 5) AS BIGINT) FROM myTable1 but it allows for the space character to not always be there, situations where the myCol1 value is not of the form nnnnn nn if the string is nn nn then the convert to int will fail.
Remember to be careful if you use the TRIM function to remove the leading zeroes, and actually in all situations you will need to test your code with data like 00120 00 and see if it returns 12 instead of the correct value of 120.

SQL strip text and convert to integer

In my database (SQL 2005) I have a field which holds a comment but in the comment I have an id and I would like to strip out just the id, and IF possible convert it to an int:
activation successful of id 1010101
The line above is the exact structure of the data in the db field.
And no I don't want to do this in the code of the application, I actually don't want to touch it, just in case you were wondering ;-)
This should do the trick:
SELECT SUBSTRING(column, PATINDEX('%[0-9]%', column), 999)
FROM table
Based on your sample data, this that there is only one occurence of an integer in the string and that it is at the end.
I don't have a means to test it at the moment, but:
select convert(int, substring(fieldName, len('activation successful of id '), len(fieldName) - len('activation successful of id '))) from tableName
Would you be open to writing a bit of code? One option, create a CLR User Defined function, then use Regex. You can find more details here. This will handle complex strings.
If your above line is always formatted as 'activation successful of id #######', with your number at the end of the field, then:
declare #myColumn varchar(100)
set #myColumn = 'activation successful of id 1010102'
SELECT
#myColumn as [OriginalColumn]
, CONVERT(int, REVERSE(LEFT(REVERSE(#myColumn), CHARINDEX(' ', REVERSE(#myColumn))))) as [DesiredColumn]
Will give you:
OriginalColumn DesiredColumn
---------------------------------------- -------------
activation successful of id 1010102 1010102
(1 row(s) affected)
select cast(right(column_name,charindex(' ',reverse(column_name))) as int)
CAST(REVERSE(LEFT(REVERSE(#Test),CHARINDEX(' ',REVERSE(#Test))-1)) AS INTEGER)
-- Test table, you will probably use some query
DECLARE #testTable TABLE(comment VARCHAR(255))
INSERT INTO #testTable(comment)
VALUES ('activation successful of id 1010101')
-- Use Charindex to find "id " then isolate the numeric part
-- Finally check to make sure the number is numeric before converting
SELECT CASE WHEN ISNUMERIC(JUSTNUMBER)=1 THEN CAST(JUSTNUMBER AS INTEGER) ELSE -1 END
FROM (
select right(comment, len(comment) - charindex('id ', comment)-2) as justnumber
from #testtable) TT
I would also add that this approach is more set based and hence more efficient for a bunch of data values. But it is super easy to do it just for one value as a variable. Instead of using the column comment you can use a variable like #chvComment.
If the comment string is EXACTLY like that you can use replace.
select replace(comment_col, 'activation successful of id ', '') as id from ....
It almost certainly won't be though - what about unsuccessful Activations?
You might end up with nested replace statements
select replace(replace(comment_col, 'activation not successful of id ', ''), 'activation successful of id ', '') as id from ....
[sorry can't tell from this edit screen if that's entirely valid sql]
That starts to get messy; you might consider creating a function and putting the replace statements in that.
If this is a one off job, it won't really matter. You could also use a regex, but that's quite slow (and in any case mean you now have 2 problems).