SQL Server removing necessary whitespaces - sql

I'm trying to add whitespaces to a column. However, the SPACE function is not working.
Example:
SELECT LEN(('ABC' + SPACE(10)))
Returns 3 instead 13.
This behavior also happens with the REPLICATE function.
Example:
REPLICATE(' ', 5)
Returns ''
What I need:
REPLICATE(' ', 5)
Returns ' '
Editing:
This suggestion works, but it needs do add : to the string.
DECLARE #Test varchar(32);
SELECT #Test = 'ABC' + SPACE(10);
SELECT #Test + ':';
Returns ABC :
I need ABC
--This table is in SQL Server
CREATE TABLE Iten
(
Code varchar(35)
);
--This table is on DB2
CREATE TABLE Product
(
code char(35),
description varchar(100)
)
INSERT INTO Iten VALUES ('ABC');
INSERT INTO Product VALUES ('ABC', 'My Test')
SELECT
Iten.Code, Product.description,
DATALENGTH(Iten.Code),
DATALENGTH(Product.code)
FROM
Iten
INNER JOIN
IBMServerD.DatabaseD.LDAT.Product AS Product ON Iten.Code = Product.code
This query returns no rows.
Because that, I need to fill spaces on the right to Iten.Code, but it does not respect it.
If both tables were in SQL Server, it would work fine.

Try using trim functions
SELECT Iten.Code, Product.description, DataLength(Iten.Code),
DataLength(Product.code)
from Iten INNER JOIN IBMServerD.DatabaseD.LDAT.Product as Product
ON ltrim(rtrim(Iten.Code)) = ltrim(rtrim(Product.code))

'ABC' + REPLICATE(' ',10)
works

SPACE(INTEGER) is working fine
select LEN('abc'+SPACE(10)) `3`
LEN() function excludes trailing blanks/whitespaces
select DATALENGTH('abc'+SPACE(10)) `13`
using DATALENGTH() give you 13, DATALENGTH() includes trailing blanks/whitespaces

Related

SQL server trimming string

I have a query, I want to Trim a column and get the only Right side values:
Here in the pic the result is like SubAccountCode and SubaccountName but user has entered code and name in SubaccountName. I want to trim the codes from Subaccountname and update the table. T
The query I have tried is mentioned below, but I think it's not so working:
Select Substring(Subaccountname,8,20)as Name from #temp
There are several ways to do this.
When looking at your example data the easiest way would be using an replace() in the update statement.
Syntax:
REPLACE ( string_expression , string_pattern , string_replacement )
Example:
UPDATE table_name
SET column2 = replace([column2], [column1], '')
What this does it updates the column2 with the value from column2 where the value from column1 is replaced with '' nothing. In your example this does leave you with an unwanted space in front. You could trim this or try as followed:
UPDATE Test
SET [SubAccountName] = replace([SubAccountName], [SubAccountCode] + ' ', '')
If the SubAccountCode could be different from the code in the SubAccountName and you only want to remove the first 8 characters (if you are sure it is always the first 8) you can use:
UPDATE YourTable SET SubAccountName = RIGHT(SubAccountName, LEN(SubAccountName) - 7)
Example script:
create table test (
SubAccountName varchar(100),
SubAccountCode varchar(100)
)
insert into test (SubAccountCode, SubAccountName) VALUES
(1234567, '1234567 AUBC' ),
(1234467, '1234467 AUBC' ),
(1235567, '1235567 AUBC' )
select * from test -- Check that the data is like your example.
UPDATE Test SET SubAccountName = RIGHT(SubAccountName, LEN(SubAccountName) - 8)
select * from test -- Check that the result is like your wanted result.
drop table test -- Cleanup the test table.
This code will work for you.
UPDATE TableName SET SubaccountName = REPLACE(LTRIM(RTRIM(SubaccountName)),LTRIM(RTRIM(SubAccountCode)),'')

How to apply trim function inside this query [duplicate]

Below is simple sql query to select records using in condition.
--like this I have 6000 usernames
select * from tblUsers where Username in ('abc ','xyz ',' pqr ',' mnop ' );
I know there are LTrim & Rtrim in sql to remove the leading trailing spaces form left & right respectively.
I want to remove the spaces from left & right in all the usernames that I am supplying to the select query.
Note:-
I want to trim the values that I am passing in the in clause.(I don't want to pass LTrim & RTrim to each value passed).
There are no trailing space in the records but value that I am passing in the clause is copied from excel & then pasted in Visual Studio. Then using ALT key I put '(single quote) at the left & right sides of the string. Due to this some strings has spaces in the right side trailing.
How to use the trim function in the select query?
I am using MS SQL Server 2012
If I understand your question correctly you are pasting from Excel into an IN clause in an adhoc query as below.
The trailing spaces don't matter. It will still match the string foo without any trailing spaces.
But you need to ensure that there are no leading spaces.
As the source of the data is Excel why not just do it all there?
You can use formula
= CONCATENATE("'",TRIM(SUBSTITUTE(A1,"'","''")),"',")
Then copy the result (from column B in the screenshot above) and just need to trim off the extra comma from the final entry.
You can do like this:
select * from tblUsers where LTRIM(RTRIM(Username)) in (ltrim(rtrim('abc')),ltrim(rtrim('xyz')),ltrim(rtrim('pqr')),ltrim(rtrim('mnop')));
However, if you have permission to update the database. Please remove all the spaces in your Username field. It is really not good to do the query like this.
One way to tackle your problem and still be able to benefit from an index on username is to use a persisted computed column:
Setup
-- drop table dbo.tblUsers
create table dbo.tblUsers
(
UserId INT NOT NULL IDENTITY(1, 1) CONSTRAINT PK_UserTest PRIMARY KEY,
Username NVARCHAR(64) NOT NULL,
UsernameTrimmed AS LTRIM(RTRIM(Username)) PERSISTED
)
GO
-- other columns may be included here with INCLUDE (col1, col2)
CREATE INDEX IDX_UserTest ON dbo.tblUsers (UsernameTrimmed)
GO
insert into dbo.tblUsers (Username) VALUES ('abc '),('xyz '),(' pqr '), (' mnop '), ('abc'), (' useradmin '), ('etc'), (' other user ')
GO
-- some mock data to obtain a large number of records
insert into dbo.tblUsers (Username)
select top 20000 SUBSTRING(text, 1, 64) from sys.messages
GO
Test
-- this will use the index (index seek)
select * from tblUsers where UsernameTrimmed in (LTRIM(RTRIM('abc')), LTRIM(RTRIM(' useradmin ')));
This allows for faster retrievals at the expense of extra space.
In order to get rid of query construction (and the ugliness of many LTRIMs and RTRIMs), you can push searched users in a table that looks like tblUsers.
create table dbo.searchedUsers
(
Username NVARCHAR(64) NOT NULL,
UsernameTrimmed AS LTRIM(RTRIM(Username)) PERSISTED
)
GO
Push raw values into dbo.searchedUsers.Username column and the query should look like this:
select U.*
from tblUsers AS U
join dbo.searchedUsers AS S ON S.UsernameTrimmed = U.UsernameTrimmed
The big picture
It is way better to properly trim your data in the service layer of your application (C#) so that future clients of your table may rely on decent information. So, trimming should be performed both when inserting information into tblUsers and when searching for users (IN values)
select *
from tblUsers
where RTRIM(LTRIM(Username)) in ('abc','xyz','pqr','mnop');
Answer: SELECT * FROM tblUsers WHERE LTRIM(RTRIM(Username)) in ('abc','xyz','pqr','mnop');
However, please note that if you have functions in your WHERE clause it defeats the purpose of having an indexes on that column and will use a
scan than a seek.
I would propose you clean your data before inserting into tblUsers
I think you can try this:
Just replace the table2 with you table name form where you are getting the username
select * from tblUsers where Username in ((select distinct
STUFF((SELECT distinct ', ' + RTRIM(LTRIM(t1.Username))
from table2 t1
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,2,'') UserName
from table2 t) );
I'd do it in two step:
1) populate a temp table with all your strings with blanks
2) do a select with a subselect
create table a (a char(1))
insert into a values('a')
insert into a values('b')
insert into a values('c')
insert into a values('d')
create table #b (atmp char(5))
insert into #b values ('a ')
insert into #b values (' b')
insert into #b values (' c ')
select * from a where a in (select ltrim(rtrim(atmp)) from #b)

Replace ; with blank in SQL

I have a table like this:
DECLARE #T TABLE
(note VARCHAR (50))
INSERT #T
SELECT 'Amplifier'
UNION ALL SELECT ';'
UNION ALL SELECT 'Regulator'
How can I replace the semicolon (';') with blank ('').
Expected Output:
Amplifier
'' -- here semicolon replace with blank
Regulator
If you want to replace ALL semicolons from any outputted cell you can use REPLACE like this:
SELECT REPLACE(note,';','') AS [note] FROM #T
Fetching from the given table, use a CASE statement:
SELECT CASE WHEN note = ';' THEN '' ELSE note END AS note FROM #T;
replace() would replace all occurrences of the character. Doesn't seem like you'd want that. This expression only replaces exact matches of the whole string.
It looks like you need to REPLACE all your semicolons:
DECLARE #T TABLE
(note VARCHAR (50))
INSERT INTO #T
SELECT REPLACE(SourceColumn, ';', '')
FROM SourceTable
SQL Server 2017 introduced the function TRANSLATE where you can specifiy a list of characters to be replaced
SELECT TRANSLATE('MAX(0,MIN(h-36,8))', '(,-)', ' ') -->'MAX 0 MIN h 36 8 '

Extracting specific column values embedded within composite Strings of codes

I am trying to create a piece of code in sql server 2008 that will grab specific values from each distinct string within my dbo table. The ultimate goal is to make a drop down box within Visual Studio so that one can choose all lines from the database that contain a specific product code (see definition of product code below). Example strings:
in_0314_95pf_500_w_0315
in_0314_500_95pf_0315_w
The part of these strings I am wishing to identify is the 3 digit numeric code (in this case let us call it product code) that appears once within each string. There are roughly 300 different product codes.
The problem is that these product code values do not appear in the same position within each unique string. Hence, I am having a hard time determining the product code because I can't use substring, charindex, like, etc.
Any ideas? Any help is MUCH appreciated.
This can be done with PATINDEX:
DECLARE #s NVARCHAR(100) = 'in_0314_95pf_500_w_0315'
SELECT SUBSTRING(#s, PATINDEX('%[_][0-9][0-9][0-9][_]%', #s) + 1, 3)
Output:
500
If there are no underscores then:
SELECT SUBSTRING(#s, PATINDEX('%[^0-9][0-9][0-9][0-9][^0-9]%', #s) + 1, 3)
This means 3 digits between any symbols that are not digits.
EDIT:
Apply to table like:
SELECT SUBSTRING(ColumnName, PATINDEX('%[^0-9][0-9][0-9][0-9][^0-9]%', ColumnName) + 1, 3)
FROM TableName
One approach is to use a String splitting table function like this one which breaks the string up into its components. You can then filter the components based on your criteria:
SELECT Name
FROM dbo.splitstring('in_0314_95pf_500_w_0315', '_')
WHERE ISNUMERIC(Name) = 1 AND LEN(Name) = 3;
I've amended the function slightly to accept the delimiter as a parameter.
CREATE FUNCTION dbo.splitstring ( #stringToSplit VARCHAR(MAX), #delimiter VARCHAR(50))
RETURNS
#returnList TABLE ([Name] [nvarchar] (500))
AS
BEGIN
DECLARE #name NVARCHAR(255)
DECLARE #pos INT
WHILE CHARINDEX(#delimiter, #stringToSplit) > 0
BEGIN
SELECT #pos = CHARINDEX(#delimiter, #stringToSplit)
SELECT #name = SUBSTRING(#stringToSplit, len(#delimiter), #pos-len(#delimiter))
INSERT INTO #returnList
SELECT #name
SELECT #stringToSplit = SUBSTRING(#stringToSplit, #pos+LEN(#delimiter),
LEN(#stringToSplit)-#pos)
END
INSERT INTO #returnList
SELECT #stringToSplit
RETURN
END
To apply this to your table, use CROSS APPLY (Single Delimiter):
SELECT mt.Name, x.Name AS ProductCode
FROM MyTable mt
CROSS APPLY dbo.splitstring(mt.Name, '_') x
WHERE ISNUMERIC(x.Name) = 1 AND LEN(x.Name) = 3
Update, Multiple Delimiters
I guess the real underlying problem is that ultimately the product codes need to be normalized out of the composite key (e.g. add a distinct ProductId or ProductCode column to the same table), derived using a query like this, and then stored back in the table via an update. Reverse engineering the product codes out of the string appears to be a trial and error process.
Nonetheless, you can continue to keep passing the split strings through further splitting functions (one per each type of delimiter), before applying your final discriminating filter:
SELECT *
FROM MyTable mt
CROSS APPLY dbo.splitstring(mt.Name, 'test') y -- First alias
CROSS APPLY dbo.splitstring(y.Name, '_') x -- Reference the preceding alias
WHERE ISNUMERIC(x.Name) = 1 AND LEN(x.Name) = 3; -- Must reference the last alias (x)
Note that the stringsplit function has again been changed to accommodate multicharacter delimiters.
If you have a table (or can generate in inline view) of the product codes, you can join the list of long strings to the product codes with a like clause.
Create Table longcodes (
longcode varchar(20)
)
Create Table products (
prodCode char(3)
)
insert products values('100')
insert products values('111')
insert products values('123')
insert longcodes values ('abc_a_100_test')
insert longcodes values ('asdf_111_bob')
insert longcodes values ('in_0314_123_95pf')
insert longcodes values ('f_100_u')
insert longcodes values ('hihi_111_bye')
insert longcodes values ('in_123_0314_95pf')
insert longcodes values ('a_b__c_d_100_efg')
select *
from products p
join longcodes l on l.longcode like '%_' + p.prodCode + '_%'
And they get aligned with the product codes like this:
prodCode longcode
100 abc_a_100_test
100 f_100_u
100 a_b__c_d_100_efg
111 asdf_111_bob
111 hihi_111_bye
123 in_0314_123_95pf
123 in_123_0314_95pf
EDIT: Seeing the developments in the other answer, you can simplify the like clause to
like p.prodCode
and just deal with the fact that you have a much greater chance of a single composite string producing multiple matches.

What is the simplest/best way to remove substrings at the end of a string?

I have a function that normalizes addresses. What I would like to do now is remove any of the strings in a limited, specified list if they occur at the end of the string. Let's say the strings I want to remove are 'st', 'ave', 'rd', 'dr', 'ct'... If the string ends with any of these strings, I want to remove them. What is the best way to accomplish this, using T-SQL (this will not be part of a select statement)?
Edit:
This is a function that accepts one address and formats it. I would like to inline the code, and the list, but in the simplest way possible. For example, some code that I've been playing with is:
if #address LIKE '%st'
SET #address = substring(#address, 1, PatIndex('%st', #address) - 1)
Is this a good method? How can I put it in some sort of loop so I can repeat this code with different values (other than st)?
Adding the values to be trimmed to a new table allows you to
easily add new values
use this table to clean up adresses
SQL Statement
DECLARE #Input VARCHAR(32)
SET #Input = 'Streetsstaverddrad'
DECLARE #Trim TABLE (Value VARCHAR(32))
INSERT INTO #Trim
SELECT 'st'
UNION ALL SELECT 'ave'
UNION ALL SELECT 'rd'
UNION ALL SELECT 'dr'
UNION ALL SELECT 'ad'
WHILE EXISTS (
SELECT *
FROM (
SELECT [Adres] = #Input
) i
INNER JOIN #Trim t ON i.Adres LIKE '%' + t.Value
)
BEGIN
SELECT #Input = SUBSTRING(Adres, 1, LEN(Adres) - LEN(t.Value))
FROM (
SELECT [Adres] = #Input
) i
INNER JOIN #Trim t ON i.Adres LIKE '%' + t.Value
END
SELECT #Input
In SQL Server 2005 it is possible to define a user-function which enables regular expression matching. You will need to defined a function which strips the trailing strings. A RegEx to match the scenarios you mention would be something like...
\s+(ave|rd|dr|ct)\s*$