Replacing empty string in SQL using SELECT - sql

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

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.

Allow leading zeros in a LIKE statement

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))

Insert a negative value with minus sign at end

I want to insert a value into an sql server 2008 table.
The value are like 20.00- , 10.00-
The minus sign is at the end of the value.
How can I achieve this?
How about using something like this?
SELECT REPLACE(CAST(-456.00 AS VARCHAR(10)),'-','') + '-'
Where 456.00 is your value
You could insert raw data into a staging table first. Then you could either convert the values in the staging table and insert them afterwards into the actual table, or insert and convert at the same time.
Here's how you could go about the conversion.
For every input value, you would need to check if it has a minus. If it does, then one character should be deleted at the last position and one character should be inserted at the first position. Otherwise nothing should be deleted or inserted.
So, essentially you can have an indication in the form of 1 or 0 and use that number to determine how many characters to insert or delete.
There are various methods of obtaining that 1/0 result.
For instance, you could take the input value's last character as a substring and use CHARINDEX to search for - within that substring:
CHARINDEX('-', LEFT(InputValue, LEN(InputValue)))
If the last character of InputValue is '-', the CHARINDEX will return 1, otherwise it will return 0.
Another method, also using CHARINDEX, would be to go like this:
CAST(CHARINDEX('-', InputValue) AS bit)
If InputValue has a minus, CHARINDEX will return a positive result and CAST will convert it to 1. If there is no minus, CHARINDEX will give you a 0, which will stay 0 after the cast.
Now you can use the expression's result to determine:
whether to delete the last character or not:
STUFF(InputValue, LEN(InputValue), CAST(CHARINDEX('-', InputValue) AS bit), '')
and
whether to prefix the value with a '-':
REPLICATE('-', CAST(CHARINDEX('-', InputValue) AS bit))
That is, the complete expression is this:
REPLICATE('-', CAST(CHARINDEX('-', InputValue) AS bit)) +
STUFF(InputValue, LEN(InputValue), CAST(CHARINDEX('-', InputValue) AS bit), '')
In the final statement you could also use CROSS APPLY to avoid repetition of the emphasised sub-expression, something aloong the lines of this (assuming you will choose to do insertion + processing):
INSERT INTO dbo.TargetTable (columns)
SELECT
...
REPLICATE('-', x.HasMinus) + STUFF(InputValue, LEN(InputValue), x.HasMinus, ''),
...
FROM dbo.StagingTable
CROSS APPLY (SELECT CAST(CHARINDEX('-', InputValue) AS bit)) AS x (HasMinus)
;
It is long but :
select IIF(ISNUMERIC(IIF(RIGHT(RTRIM('20.55-'), 1) = '-', '-' + REPLACE('20.55-', '-',''), '20.55-')) = 1, CONVERT(decimal(7,3), IIF(RIGHT(RTRIM('20.55-'), 1) = '-', '-' + REPLACE('20.55-', '-',''), '20.55-')), NULL)
Simply :
Select CASE WHEN LEFT(InputValue,1) = '-' THEN '-' ELSE '' END + REPLACE(InputValue,'-','')
You may need to Cast it as money (or numeric or decimal)

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.

How can I remove leading and trailing quotes in SQL Server?

I have a table in a SQL Server database with an NTEXT column. This column may contain data that is enclosed with double quotes. When I query for this column, I want to remove these leading and trailing quotes.
For example:
"this is a test message"
should become
this is a test message
I know of the LTRIM and RTRIM functions but these workl only for spaces. Any suggestions on which functions I can use to achieve this.
I have just tested this code in MS SQL 2008 and validated it.
Remove left-most quote:
UPDATE MyTable
SET FieldName = SUBSTRING(FieldName, 2, LEN(FieldName))
WHERE LEFT(FieldName, 1) = '"'
Remove right-most quote: (Revised to avoid error from implicit type conversion to int)
UPDATE MyTable
SET FieldName = SUBSTRING(FieldName, 1, LEN(FieldName)-1)
WHERE RIGHT(FieldName, 1) = '"'
I thought this is a simpler script if you want to remove all quotes
UPDATE Table_Name
SET col_name = REPLACE(col_name, '"', '')
You can simply use the "Replace" function in SQL Server.
like this ::
select REPLACE('this is a test message','"','')
note: second parameter here is "double quotes" inside two single quotes and third parameter is simply a combination of two single quotes. The idea here is to replace the double quotes with a blank.
Very simple and easy to execute !
My solution is to use the difference in the the column values length compared the same column length but with the double quotes replaced with spaces and trimmed in order to calculate the start and length values as parameters in a SUBSTRING function.
The advantage of doing it this way is that you can remove any leading or trailing character even if it occurs multiple times whilst leaving any characters that are contained within the text.
Here is my answer with some test data:
SELECT
x AS before
,SUBSTRING(x
,LEN(x) - (LEN(LTRIM(REPLACE(x, '"', ' ')) + '|') - 1) + 1 --start_pos
,LEN(LTRIM(REPLACE(x, '"', ' '))) --length
) AS after
FROM
(
SELECT 'test' AS x UNION ALL
SELECT '"' AS x UNION ALL
SELECT '"test' AS x UNION ALL
SELECT 'test"' AS x UNION ALL
SELECT '"test"' AS x UNION ALL
SELECT '""test' AS x UNION ALL
SELECT 'test""' AS x UNION ALL
SELECT '""test""' AS x UNION ALL
SELECT '"te"st"' AS x UNION ALL
SELECT 'te"st' AS x
) a
Which produces the following results:
before after
-----------------
test test
"
"test test
test" test
"test" test
""test test
test"" test
""test"" test
"te"st" te"st
te"st te"st
One thing to note that when getting the length I only need to use LTRIM and not LTRIM and RTRIM combined, this is because the LEN function does not count trailing spaces.
I know this is an older question post, but my daughter came to me with the question, and referenced this page as having possible answers. Given that she's hunting an answer for this, it's a safe assumption others might still be as well.
All are great approaches, and as with everything there's about as many way to skin a cat as there are cats to skin.
If you're looking for a left trim and a right trim of a character or string, and your trailing character/string is uniform in length, here's my suggestion:
SELECT SUBSTRING(ColName,VAR, LEN(ColName)-VAR)
Or in this question...
SELECT SUBSTRING('"this is a test message"',2, LEN('"this is a test message"')-2)
With this, you simply adjust the SUBSTRING starting point (2), and LEN position (-2) to whatever value you need to remove from your string.
It's non-iterative and doesn't require explicit case testing and above all it's inline all of which make for a cleaner execution plan.
The following script removes quotation marks only from around the column value if table is called [Messages] and the column is called [Description].
-- If the content is in the form of "anything" (LIKE '"%"')
-- Then take the whole text without the first and last characters
-- (from the 2nd character and the LEN([Description]) - 2th character)
UPDATE [Messages]
SET [Description] = SUBSTRING([Description], 2, LEN([Description]) - 2)
WHERE [Description] LIKE '"%"'
You can use following query which worked for me-
For updating-
UPDATE table SET colName= REPLACE(LTRIM(RTRIM(REPLACE(colName, '"', ''))), '', '"') WHERE...
For selecting-
SELECT REPLACE(LTRIM(RTRIM(REPLACE(colName, '"', ''))), '', '"') FROM TableName
you could replace the quotes with an empty string...
SELECT AllRemoved = REPLACE(CAST(MyColumn AS varchar(max)), '"', ''),
LeadingAndTrailingRemoved = CASE
WHEN MyTest like '"%"' THEN SUBSTRING(Mytest, 2, LEN(CAST(MyTest AS nvarchar(max)))-2)
ELSE MyTest
END
FROM MyTable
Some UDFs for re-usability.
Left Trimming by character (any number)
CREATE FUNCTION [dbo].[LTRIMCHAR] (#Input NVARCHAR(max), #TrimChar CHAR(1) = ',')
RETURNS NVARCHAR(max)
AS
BEGIN
RETURN REPLACE(REPLACE(LTRIM(REPLACE(REPLACE(#Input,' ','¦'), #TrimChar, ' ')), ' ', #TrimChar),'¦',' ')
END
Right Trimming by character (any number)
CREATE FUNCTION [dbo].[RTRIMCHAR] (#Input NVARCHAR(max), #TrimChar CHAR(1) = ',')
RETURNS NVARCHAR(max)
AS
BEGIN
RETURN REPLACE(REPLACE(RTRIM(REPLACE(REPLACE(#Input,' ','¦'), #TrimChar, ' ')), ' ', #TrimChar),'¦',' ')
END
Note the dummy character '¦' (Alt+0166) cannot be present in the data (you may wish to test your input string, first, if unsure or use a different character).
To remove both quotes you could do this
SUBSTRING(fieldName, 2, lEN(fieldName) - 2)
you can either assign or project the resulting value
You can use TRIM('"' FROM '"this "is" a test"') which returns: this "is" a test
CREATE FUNCTION dbo.TRIM(#String VARCHAR(MAX), #Char varchar(5))
RETURNS VARCHAR(MAX)
BEGIN
RETURN SUBSTRING(#String,PATINDEX('%[^' + #Char + ' ]%',#String)
,(DATALENGTH(#String)+2 - (PATINDEX('%[^' + #Char + ' ]%'
,REVERSE(#String)) + PATINDEX('%[^' + #Char + ' ]%',#String)
)))
END
GO
Select dbo.TRIM('"this is a test message"','"')
Reference : http://raresql.com/2013/05/20/sql-server-trim-how-to-remove-leading-and-trailing-charactersspaces-from-string/
I use this:
UPDATE DataImport
SET PRIO =
CASE WHEN LEN(PRIO) < 2
THEN
(CASE PRIO WHEN '""' THEN '' ELSE PRIO END)
ELSE REPLACE(PRIO, '"' + SUBSTRING(PRIO, 2, LEN(PRIO) - 2) + '"',
SUBSTRING(PRIO, 2, LEN(PRIO) - 2))
END
Try this:
SELECT left(right(cast(SampleText as nVarchar),LEN(cast(sampleText as nVarchar))-1),LEN(cast(sampleText as nVarchar))-2)
FROM TableName