Remove multiple spaces to a single space in sybase - tsql

i am using below query to remove consecutive multiple spaces to a single space . the loop is not coming out where did i made mistake . please help me out with this or if anyother better idea to handle this.
DECLARE #MEME_LAST_NAME VARCHAR(22)
select #MEME_LAST_NAME = 'Kawamur a '
WHILE (PATINDEX('% %', #MEME_LAST_NAME ) > 0)
BEGIN
SET #MEME_LAST_NAME = STR_REPLACE(#MEME_LAST_NAME,' ','')
END
select #MEME_LAST_NAME
output should be : 'Kawamur a '

replace space with null
select str_replace('Kawamur a '," " ,NULL)

set nocount on
declare #mesg_text varchar(50)
select #mesg_text = "'Kawamur a '"
while (charindex(" ",#mesg_text) > 0)
begin
select #mesg_text = str_replace(#mesg_text," "," ")
end
select #mesg_text
'Kawamur a '
Single quotes put on string only to highlight single space at the end.

Related

Why wont Rtrim clear spaces (for comparison)

I have a a col that is a text field (i know not used any more) that i need to compare. (the instruction field is a text field)
Case when rtrim(cast(RT.INSTRUCTIONS as varchar(max))) = rtrim(cast(HQ.INSTRUCTIONS as varchar(max))) then 'TRUE' Else 'FALSE' end as INSTRUCTIONS.
the value in RT.Instructions is "Check the oil levels every 30 hours. "
the value in HQ.Instructions is "Check the oil levels every 30 hours."
Why wont the trailing blank go away. i did a len on both and hq is 1 less then the rt value.
I also am having the same issue on a varchar(60) field.
Perhaps there is a character that isn't being picked up. Maybe the following will be useful in finding that value. Or maybe just get you started down the right path.
DECLARE #Char INT = 0
DECLARE #Tab TABLE (Id INT, Chr VARCHAR(5), Instructions VARCHAR(MAX), c VARCHAR(MAX))
WHILE #Char < = 256
BEGIN
INSERT INTO #Tab
SELECT Id
,CONVERT(NVARCHAR,CHAR(#Char)) Chr
,CONVERT(NVARCHAR,RIGHT(RTRIM(rt.Instructions),1)) InstructionChar
,CONVERT(NVARCHAR,CHAR(CONVERT(int,#Char))) c
FROM YourTable
WHERE RIGHT(RTRIM(Instructions),1) LIKE '%'+CHAR(CONVERT(int,#Char))
AND RIGHT(RTRIM(Instructions),1) NOT LIKE '[A-Za-z]'
AND RIGHT(RTRIM(Instructions),1) NOT LIKE '[0-9]'
AND RIGHT(RTRIM(Instructions),1) NOT LIKE '.'
AND RIGHT(RTRIM(Instructions),1) NOT LIKE ']'
AND RIGHT(RTRIM(Instructions),1) NOT LIKE ')'
AND RIGHT(RTRIM(Instructions),1) NOT LIKE '"'
AND RIGHT(RTRIM(Instructions),1) NOT LIKE '}'
AND RIGHT(RTRIM(Instructions),1) NOT LIKE '/'
SET #Char = #Char + 1
END
SELECT DISTINCT *
FROM #Tab
Sorry : I'm not allowed to write comments yet
First try :
Case when left(rtrim(cast(RT.INSTRUCTIONS as varchar(max))),len(HQ.INSTRUCTIONS)) = rtrim(cast(HQ.INSTRUCTIONS as varchar(max))) then 'TRUE' Else 'FALSE' end as INSTRUCTIONS
To check if no other issue is concerned.
Then do :
SELECT ASCII(right(RT.INSTRUCTIONS,1))
To confirm that the trailling space is a "real" space : this query should display 32.
CHAR(32) => ' '
ASCII (' ') => 32
I bet you will get 16O. 160 means the last caracter is an non-breaking space witch is not concerned by trim functions...
If so, you will have to build a scalar function like :
ALTER FUNCTION [dbo].[fn_Replace_NonBreakingSpace]
(
#InputString varchar(max),
)
RETURNS varchar(MAX)
AS
BEGIN
RETURN REPLACE(#InputString, char(160), char(32))
END
And then :
Case when rtrim(dbo.fn_Replace_NonBreakingSpace(RT.INSTRUCTIONS)) = rtrim(dbo.fn_Replace_NonBreakingSpace(HQ.INSTRUCTIONS)) then 'TRUE' Else 'FALSE' end as INSTRUCTIONS

How can i pass parameters to a Common Table Expression inside a sp?

I want to rewrite a functioning, but slow stored procedure using CTE (common table Expression)
I have a big stored procedure where i build the nececary SQL dynamicaly based on parameter used. Currently there are 27 parameters, i compose the SQL string that i execute at the end it looks like:
DECLARE #SqlWhereClause NVARCHAR(MAX)
SET #SqlWhereClause = ' WHERE ([InTimeStamp] BETWEEN ''' + CONVERT(VARCHAR(19), #fromDate, 120) + ''' AND ''' + CONVERT(VARCHAR(19), #toDate, 120) + ''')'
IF #showOnlyErrors = '1'
BEGIN
SET #SqlWhereClause += ' AND Status = ''Error'''
END
IF LEN(LTRIM(RTRIM(#docNo))) > 0
BEGIN
IF #matchExact = '1'
BEGIN
SET #SqlWhereClause += ' AND DocumentNumber = ''' + #docNo + ''''
END
ELSE
BEGIN
SET #SqlWhereClause += ' AND (contains([DocumentNumber],'''+ #docNo +'''))'
END
END
At the end, i add the pagination and transform it to the final formSQL:
IF CONVERT(int, LTRIM(RTRIM(#takeRows))) > 0
BEGIN
SET #SqlOrderByClause += ' OFFSET ' + #rowNumberToSkip +' ROWS FETCH NEXT '+ #takeRows +' ROWS ONLY '
Set #RowCount = ' Select #totalRecords = count(1) from dbo.Messages WITH (NOLOCK) ' + #SqlWhereClause
END
SET #SQL = #SqlSelect + #SqlFrom + #SqlWhereClause + #SqlOrderByClause + ' ; ' + #RowCount
PRINT #SQL
EXECUTE sp_executesql #SQL, #params, #totalRecords OUTPUT
Everithing is working like a charm. No problems. Only performance problems. To solve one of it, i would try to use CTE (common table extpression)
But this is not working:
With DataSQL AS
(#SqlSelect + #SqlFrom + #SqlWhereClause + #SqlOrderByClause),
- incorrect syntax near #SqlSelect - Expecting '(' or Select.
I also tried this one:
WITH DataSQL AS
( Select #SqlSelect From #SqlFromFast
Where #SqlWhereClause Order By #SqlOrderByClause),
here i get:
An expression of non-boolean type specified in a context where a condition is expected, near 'Order'
Any idea? Or is it not possible to use CTE with multiple variables? All i found until now are simply queries with one, maybe two variables.
You could try:
WITH DataSQL AS
(
SELECT #SqlSelect SqlSelect
, #SqlFromFast SqlFromFast
, etcetera
)
Make sure you give aliases, or it won't work. I doubt it will help your performance issues though. You could try to use a temp table, that's usually quicker. you could also try to use inner variables:
DECLARE #Select VARCHAR(MAX) = #SQLSelect
And use those instead, that may help the optimizer, though that depends on your data.

Getting upper into lower case

In my SELECT statement, I have:
,UserName
When this comes through in the query, it appears as: JOHN.SMITH
Is it possible to use CAST or CONVERT to change this to John Smith?
Any advice gratefully appreciated.
Thanks.
First replace the period with a space:
SELECT REPLACE(SELECT UserName FROM YourTable, '.', ' ')
Save this in a variable, or put this select directly to the function below.
Unfortunately, I don't have t-sql at my disposal right now, so I can't check the syntax to be 100% correct.
Then to set only first chars to uppercase. If you were using oracle, I would tell you to use initcap, but this doesn't exist in t-sql.
Taken from link: http://www.devx.com/tips/Tip/17608
create function initcap (#text varchar(4000))
returns varchar(4000)
as
begin
declare #counter int,
#length int,
#char char(1),
#textnew varchar(4000)
set #text = rtrim(#text)
set #text = lower(#text)
set #length = len(#text)
set #counter = 1
set #text = upper(left(#text, 1) ) + right(#text, #length - 1)
while #counter <> #length --+ 1
begin
select #char = substring(#text, #counter, 1)
IF #char = space(1) or #char = '_' or #char = ',' or #char = '.' or #char = '\'
or #char = '/' or #char = '(' or #char = ')'
begin
set #textnew = left(#text, #counter) + upper(substring(#text,
#counter+1, 1)) + right(#text, (#length - #counter) - 1)
set #text = #textnew
end
set #counter = #counter + 1
end
return #text
end
So use this function to convert the uppercase string. Hope this helps.
You could go about it like so:
DECLARE #UserName AS varchar(50) = 'JOHN.SMITH'
SELECT LEFT(UPPER(LEFT(#UserName, CHARINDEX('.', #UserName)-1)),1) + SUBSTRING(LOWER(LEFT(#UserName, CHARINDEX('.', #UserName)-1)),2,LEN(LEFT(#UserName, CHARINDEX('.', #UserName)-1))-1) + ' ' + LEFT(UPPER(RIGHT(#UserName, LEN(#UserName) - CHARINDEX('.', #UserName))),1) + SUBSTRING(LOWER(RIGHT(#UserName, LEN(#UserName) - CHARINDEX('.', #UserName))),2,LEN(RIGHT(#UserName, LEN(#UserName) - CHARINDEX('.', #UserName)))-1)
It gets everything before the . and then uppers the first letter whilst lowering the rest and then does the same for everything after the ..
However, it would be much better if you handled this in your code as when you come back to reading this query you may not know what it's doing.

In SSMS copied string has different behaviour to original string

I am attempting to semi automate creation of my databases
As part of this I want to add extended properties of column descriptions.
When I try to run sp_sqlexec in my script ( or even just Exec(#mystring) I get an error. However, if while debugging, I copy the dynamic sql string from the watch window and then run sp_sqlexec on the copied string in a seperate window I get no errors and the extended properties are added correctly.
The following script demonstrates the problem:
--Create a table to apply column descriptions to
Create table dbo.table1 (id int, name nvarchar(20));
--Create the table that contains our column descriptions
Create table dbo.column_descs_table (schemaname nvarchar(20), tablename nvarchar(20), columnname nvarchar(20), column_description nvarchar(20))
Insert into column_descs_table (schemaname, tablename, columnname, column_description)
values ('dbo', 'table1', 'id', 'the id column'), ('dbo' , 'table1', 'name', 'the name column');
--Dynamic sql string varaible to hold the commands
Declare #dyn_sql nvarchar(max);
Set #dyn_sql = 'N'''; --Set to opening quote
--now create the string containing commands to add column escriptions
SELECT #dyn_sql = #dyn_sql + N' EXEC sp_addextendedproperty ''''Col Desc'''', ''''' + column_description + N''''', ''''SCHEMA'''', ' + schemaname + N', ''''TABLE'''', ' + tablename + N', ''''COLUMN'''', ' + columnname + N' ;'
FROM dbo.column_descs_table
Set #dyn_sql = #dyn_sql + ''''; --add the closing quote
Print #dyn_sql --If I copy the contents of #dyn_sql here and run seperately it works OK
Exec sp_sqlexec #dyn_sql -- this line causes error
The error I get is
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near ' EXEC sp_addextendedproperty 'Col Desc', 'the id column', 'SCHEMA', dbo, 'TABLE', table1, 'COLUMN', id ; EXEC sp_addextendedprope'.
Yet if I step through the code and copy the contents of #dyn_sql then paste this as follows:
Exec sp_sqlexec N' EXEC sp_addextendedproperty ''Col Desc'', ''the id column'', ''SCHEMA'', dbo, ''TABLE'', table1, ''COLUMN'', id ; EXEC sp_addextendedproperty ''Col Desc'', ''the name column'', ''SCHEMA'', dbo, ''TABLE'', table1, ''COLUMN'', name ;'
Then the above works fine and the column descriptions are added as expected.
Any help on this specific copying problem is much appreciated. I do understand the security issues with dynamic sql ( this script will be removed from the database once my setup is complete)
Thanks in advance
Jude
It looks like it's because your leading N is included within the string to execute; you don't need it at all. In other words, you are ending up with something like this:
exec sp_execsql 'N'' exec sp_addextendedproperty /* etc. */ '''
But it should be like this:
exec sp_execsql N'exec sp_addextendedproperty /* etc. */ '
But why are you even using dynamic SQL here? All values passed to sp_addextendedproperty can be passed as parameters so there is no obvious reason to use dynamic SQL, unless you've simplified something for the question.
Finally, you should be using sp_executesql, it's the preferred way to execute dynamic SQL.
I believe that I have resolved my string copying problem. SQL was detecting double quotes in by concatenated string as empty strings and removing them. A simple example showing the problem and my solution is below:
--Example to Select 'simple string' and then 'concat string' into results sets
DECLARE
#Simplestring nvarchar( max ) = '' ,
#Concatstring nvarchar( max ) = '' ,
#Stringvar nvarchar( 10 ) = 'string';
--The double quotes in next line are the quotemark we want plus a quotemark acting
--as an escape character
--#simplestring will be set to 'Select 'simple string' '
SET #Simplestring = 'Select ''simple string'' ';
--Similarly we need #concatstring to be set to 'Select 'Concat string' '
SET #Concatstring = 'Select '' concat' + #Stringvar + ''; -- this wont work the last
--double quote will be removed
--Add a character that cannot appear in any othe part of the concatenation - I've used *
SET #Concatstring = 'Select '' Concat ' + #Stringvar + '*';
--Now replace the * with a quote mark
SET #Concatstring = REPLACE( #Concatstring , '*' , '''' ); -- This will work
EXEC sp_executesql #Simplestring;
EXEC sp_executesql #Concatstring;
There may be a simpler solution than mine.
Many thanks for the advice on using sp_executesql. I am working on changing my code to use this ( with variables passed in as parametrs).
Jude

Replace a newline in TSQL

I would like to replace (or remove) a newline character in a TSQL-string.
Any Ideas?
The obvious
REPLACE(#string, CHAR(13), '')
just won't do it...
Actually a new line in a SQL command or script string can be any of CR, LF or CR+LF. To get them all, you need something like this:
SELECT REPLACE(REPLACE(#str, CHAR(13), ''), CHAR(10), '')
REPLACE(#string, CHAR(13) + CHAR(10), '')
I may be a year late to the party, but I work on queries & MS-SQL every day, and I got tired of the built-in functions LTRIM() & RTRIM() (and always having to call them together), and of not catching 'dirty' data that had newlines at the end, so I decided it was high time to implement a better TRIM function. I'd welcome peer feedback!
Disclaimer: this actually removes (replaces with a single whitespace) extended forms of whitespace (tab, line-feed, carriage-return, etc.), so it's been renamed as "CleanAndTrim" from my original answer. The idea here is that your string doesn't need such extra special-whitespace characters inside it, and so if they don't occur at the head/tail, they should be replaced with a plain space. If you purposefully stored such characters in your string (say, your column of data that you're about to run this on), DON'T DO IT! Improve this function or write your own that literally just removes those characters from the endpoints of the string, not from the 'body'.
Okay, now that the disclaimer is updated, here's the code.
-- =============================================
-- Description: TRIMs a string 'for real' - removes standard whitespace from ends,
-- and replaces ASCII-char's 9-13, which are tab, line-feed, vert tab,
-- form-feed, & carriage-return (respectively), with a whitespace
-- (and then trims that off if it's still at the beginning or end, of course).
-- =============================================
CREATE FUNCTION [fn_CleanAndTrim] (
#Str nvarchar(max)
)
RETURNS nvarchar(max) AS
BEGIN
DECLARE #Result nvarchar(max)
SET #Result = LTRIM(RTRIM(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
LTRIM(RTRIM(#Str)), CHAR(9), ' '), CHAR(10), ' '), CHAR(11), ' '), CHAR(12), ' '), CHAR(13), ' ')))
RETURN #Result
END
Cheers!
Another Disclaimer:
Your typical Windows line-break is CR+LF, so if your string contains those, you'd end up replacing them with "double" spaces.
UPDATE, 2016:
A new version that gives you the option to replace those special-whitespace characters with other characters of your choice! This also includes commentary and the work-around for the Windows CR+LF pairing, i.e. replaces that specific char-pair with a single substitution.
IF OBJECT_ID('dbo.fn_CleanAndTrim') IS NULL
EXEC ('CREATE FUNCTION dbo.fn_CleanAndTrim () RETURNS INT AS BEGIN RETURN 0 END')
GO
-- =============================================
-- Author: Nate Johnson
-- Source: http://stackoverflow.com/posts/24068265
-- Description: TRIMs a string 'for real' - removes standard whitespace from ends,
-- and replaces ASCII-char's 9-13, which are tab, line-feed, vert tab, form-feed,
-- & carriage-return (respectively), with a whitespace or specified character(s).
-- Option "#PurgeReplaceCharsAtEnds" determines whether or not to remove extra head/tail
-- replacement-chars from the string after doing the initial replacements.
-- This is only truly useful if you're replacing the special-chars with something
-- **OTHER** than a space, because plain LTRIM/RTRIM will have already removed those.
-- =============================================
ALTER FUNCTION dbo.[fn_CleanAndTrim] (
#Str NVARCHAR(MAX)
, #ReplaceTabWith NVARCHAR(5) = ' '
, #ReplaceNewlineWith NVARCHAR(5) = ' '
, #PurgeReplaceCharsAtEnds BIT = 1
)
RETURNS NVARCHAR(MAX) AS
BEGIN
DECLARE #Result NVARCHAR(MAX)
--The main work (trim & initial replacements)
SET #Result = LTRIM(RTRIM(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
LTRIM(RTRIM(#Str)) --Basic trim
, NCHAR(9), #ReplaceTabWith), NCHAR(11), #ReplaceTabWith) --Replace tab & vertical-tab
, (NCHAR(13) + NCHAR(10)), #ReplaceNewlineWith) --Replace "Windows" linebreak (CR+LF)
, NCHAR(10), #ReplaceNewlineWith), NCHAR(12), #ReplaceNewlineWith), NCHAR(13), #ReplaceNewlineWith))) --Replace other newlines
--If asked to trim replacement-char's from the ends & they're not both whitespaces
IF (#PurgeReplaceCharsAtEnds = 1 AND NOT (#ReplaceTabWith = N' ' AND #ReplaceNewlineWith = N' '))
BEGIN
--Purge from head of string (beginning)
WHILE (LEFT(#Result, DATALENGTH(#ReplaceTabWith)/2) = #ReplaceTabWith)
SET #Result = SUBSTRING(#Result, DATALENGTH(#ReplaceTabWith)/2 + 1, DATALENGTH(#Result)/2)
WHILE (LEFT(#Result, DATALENGTH(#ReplaceNewlineWith)/2) = #ReplaceNewlineWith)
SET #Result = SUBSTRING(#Result, DATALENGTH(#ReplaceNewlineWith)/2 + 1, DATALENGTH(#Result)/2)
--Purge from tail of string (end)
WHILE (RIGHT(#Result, DATALENGTH(#ReplaceTabWith)/2) = #ReplaceTabWith)
SET #Result = SUBSTRING(#Result, 1, DATALENGTH(#Result)/2 - DATALENGTH(#ReplaceTabWith)/2)
WHILE (RIGHT(#Result, DATALENGTH(#ReplaceNewlineWith)/2) = #ReplaceNewlineWith)
SET #Result = SUBSTRING(#Result, 1, DATALENGTH(#Result)/2 - DATALENGTH(#ReplaceNewlineWith)/2)
END
RETURN #Result
END
GO
The Newline in T-SQL is represented by CHAR(13) & CHAR(10) (Carriage return + Line Feed). Accordingly, you can create a REPLACE statement with the text you want to replace the newline with.
REPLACE(MyField, CHAR(13) + CHAR(10), 'something else')
To do what most people would want, create a placeholder that isn't an actual line breaking character. Then you can actually combine the approaches for:
REPLACE(REPLACE(REPLACE(MyField, CHAR(13) + CHAR(10), 'something else'), CHAR(13), 'something else'), CHAR(10), 'something else')
This way you replace only once. The approach of:
REPLACE(REPLACE(MyField, CHAR(13), ''), CHAR(10), '')
Works great if you just want to get rid of the CRLF characters, but if you want a placeholder, such as
<br/>
or something, then the first approach is a little more accurate.
In SQL Server 2017 & later, use Trim
Select Trim(char(10) + char(13) from #str)
it trims on starting and ending, not in the middle
the order of \r and \n does not matter
I use it to trim special characters for a file name
Select Trim(char(10) + char(13) + ' *<>' from #fileName)
If your column data type is 'text' then you will get an error message as
Msg 8116, Level 16, State 1, Line 2 Argument data type text is
invalid for argument 1 of replace function.
In this case you need to cast the text as nvarchar and then replace
SELECT REPLACE(REPLACE(cast(#str as nvarchar(max)), CHAR(13), ''), CHAR(10), '')
Sometimes
REPLACE(myString, CHAR(13) + CHAR(10), ' ')
won't work. In that case use the following snippet code:
REPLACE(REPLACE(myString, CHAR(13),''), CHAR(10), ' ')
If you have an issue where you only want to remove trailing characters, you can try this:
WHILE EXISTS
(SELECT * FROM #ReportSet WHERE
ASCII(right(addr_3,1)) = 10
OR ASCII(right(addr_3,1)) = 13
OR ASCII(right(addr_3,1)) = 32)
BEGIN
UPDATE #ReportSet
SET addr_3 = LEFT(addr_3,LEN(addr_3)-1)
WHERE
ASCII(right(addr_3,1)) = 10
OR ASCII(right(addr_3,1)) = 13
OR ASCII(right(addr_3,1)) = 32
END
This solved a problem I had with addresses where a procedure created a field with a fixed number of lines, even if those lines were empty. To save space in my SSRS report, I cut them down.
If you have have open procedure with using sp_helptext then just copy all text in new sql query and press ctrl+h button use regular expression to replace and put ^\n in find field replace with blank .
for more detail check image.enter image description here
To #Cerebrus solution: for H2 for strings "+" is not supported. So:
REPLACE(string, CHAR(13) || CHAR(10), 'replacementString')
I was wanting to sanitize the contents of a column to generate a csv file, so want to get rid of the comma (,) within the varchar as well as newline and carrage-return.
I also wanted to eventually use the generated csv to create another script (to insert rows into another db) so also needed to change ' within the varchar to '' so ended up with this...
REPLACE(REPLACE(REPLACE(REPLACE(ErrorMessage, CHAR(13), ''), CHAR(10), ''),',',''),'''','''''')
There may be other nicer ways but it got the job done.
The answer posted above/earlier that was reported to replace CHAR(13)CHAR(10) carriage return:
REPLACE(REPLACE(REPLACE(MyField, CHAR(13) + CHAR(10), 'something else'), CHAR(13), 'something else'), CHAR(10), 'something else')
Will never get to the REPLACE(MyField, CHAR(13) + CHAR(10), 'something else') portion of the code and will return the unwanted result of:
'something else''something else'
And NOT the desired result of a single:
'something else'
That would require the REPLACE script to be rewritten as such:
REPLACE(REPLACE(REPLACE(MyField, CHAR(10), 'something else'), CHAR(13), 'something else'), CHAR(13) + CHAR(10), 'something else')
As the flow first tests the 1st/Furthest Left REPLACE statement, then upon failure will continue to test the next REPLACE statement.