LPAD in SQL Server 2008 - sql-server

I can't see a function like LPAD in SQL Server 2008. For example how can I convert the following queries into T-SQL?
select LPAD(MY_VALUE,2,' ')) VALUE
FROM MY_TABLE

Basically pad it with the number of characters you are intending to select and then right the string.
Select right(replicate(' ',2) + YourFieldValue,2) from YourTable
You can use the space function instead of replicate, space(number_of_spaces), replicate just allows you to pad with alternative characters.

Manual calculations can be annoying to apply inside queries. Luckily, we can create a function:
CREATE FUNCTION LPAD
(
#string VARCHAR(MAX), -- Initial string
#length INT, -- Size of final string
#pad CHAR -- Pad character
)
RETURNS VARCHAR(MAX)
AS
BEGIN
RETURN REPLICATE(#pad, #length - LEN(#string)) + #string;
END
GO
(Please replace VARCHAR with NVARCHAR to your liking, or use an alternative algorithm.)
Then:
SELECT dbo.LPAD(MY_VALUE, 2, ' ') VALUE
FROM MY_TABLE
Should work since SQL Server 2005.

I've come up with a LPAD and RPAD function where you can use a characterstring for the pad-part.
They should work the same as the DB2 versions.
Here's the LPAD:
CREATE FUNCTION dbo.LPAD
(
#string NVARCHAR(MAX), -- Initial string
#length INT, -- Size of final string
#pad NVARCHAR(MAX) -- Pad string
)
RETURNS VARCHAR(MAX)
AS
BEGIN
RETURN SUBSTRING(REPLICATE(#pad, #length),1,#length - LEN(#string)) + #string;
END
GO
And here is the RPAD:
CREATE FUNCTION dbo.RPAD
(
#string NVARCHAR(MAX), -- Initial string
#length INT, -- Size of final string
#pad NVARCHAR(MAX) -- Pad string
)
RETURNS VARCHAR(MAX)
AS
BEGIN
RETURN #string + SUBSTRING(REPLICATE(#pad, #length),1,#length - LEN(#string));
END
GO

I needed something similar but I couldn't use '+' because then it was interpreted as an addition between the numbers '0000000000' and [seq_no]. So I used concat instead and it worked fine.
select right (concat(replicate('0', 10), next value for seq_no), 10);

Related

Split address name from number SQL server [duplicate]

I am trying to parse out a value from a string that involves getting the last index of a string. Currently, I am doing a horrible hack that involves reversing a string:
SELECT REVERSE(SUBSTRING(REVERSE(DB_NAME()), 1,
CHARINDEX('_', REVERSE(DB_NAME()), 1) - 1))
To me this code is nearly unreadable. I just upgraded to SQL Server 2016 and I hoping there is a better way.
Is there?
If you want everything after the last _, then use:
select right(db_name(), charindex('_', reverse(db_name()) + '_') - 1)
If you want everything before, then use left():
select left(db_name(), len(db_name()) - charindex('_', reverse(db_name()) + '_'))
Wrote 2 functions, 1 to return LastIndexOf for the selected character.
CREATE FUNCTION dbo.LastIndexOf(#source nvarchar(80), #pattern char)
RETURNS int
BEGIN
RETURN (LEN(#source)) - CHARINDEX(#pattern, REVERSE(#source))
END;
GO
and 1 to return a string before this LastIndexOf. Maybe it will be useful to someone.
CREATE FUNCTION dbo.StringBeforeLastIndex(#source nvarchar(80), #pattern char)
RETURNS nvarchar(80)
BEGIN
DECLARE #lastIndex int
SET #lastIndex = (LEN(#source)) - CHARINDEX(#pattern, REVERSE(#source))
RETURN SUBSTRING(#source, 0, #lastindex + 1)
-- +1 because index starts at 0, but length at 1, so to get up to 11th index, we need LENGTH 11+1=12
END;
GO
No, SQL server doesnt have LastIndexOf.
This are the available string functions
But you can always can create your own function
CREATE FUNCTION dbo.LastIndexOf(#source text, #pattern char)
RETURNS
AS
BEGIN
DECLARE #ret text;
SELECT into #ret
REVERSE(SUBSTRING(REVERSE(#source), 1,
CHARINDEX(#pattern, REVERSE(#source), 1) - 1))
RETURN #ret;
END;
GO
Once you have one of the split strings from here,you can do it in a set based way like this..
declare #string varchar(max)
set #string='C:\Program Files\Microsoft SQL Server\MSSQL\DATA\AdventureWorks_Data.mdf'
;with cte
as
(select *,row_number() over (order by (select null)) as rownum
from [dbo].[SplitStrings_Numbers](#string,'\')
)
select top 1 item from cte order by rownum desc
**Output:**
AdventureWorks_Data.mdf
CREATE FUNCTION dbo.LastIndexOf(#text NTEXT, #delimiter NTEXT)
RETURNS INT
AS
BEGIN
IF (#text IS NULL) RETURN NULL;
IF (#delimiter IS NULL) RETURN NULL;
DECLARE #Text2 AS NVARCHAR(MAX) = #text;
DECLARE #Delimiter2 AS NVARCHAR(MAX) = #delimiter;
DECLARE #Index AS INT = CHARINDEX(REVERSE(#Delimiter2), REVERSE(#Text2));
IF (#Index < 1) RETURN 0;
DECLARE #ContentLength AS INT = (LEN('|' + #Text2 + '|') - 2);
DECLARE #DelimiterLength AS INT = (LEN('|' + #Delimiter2 + '|') - 2);
DECLARE #Result AS INT = (#ContentLength - #Index - #DelimiterLength + 2);
RETURN #Result;
END
Allows for multi-character delimiters like ", " (comma space).
Returns 0 if the delimiter is not found.
Takes a NTEXT for comfort reasons as NVARCHAR(MAX)s are implicitely cast into NTEXT but not vice-versa.
Handles delimiters with leading or tailing space correctly!
Try:
select LEN('tran van abc') + 1 - CHARINDEX(' ', REVERSE('tran van abc'))
So, the last index of ' ' is : 9
I came across this thread while searching for a solution to my similar problem which had the exact same requirement but was for a different kind of database that was lacking the REVERSE function.
In my case this was for a OpenEdge (Progress) database, which has a slightly different syntax. This made the INSTR function available to me that most Oracle typed databases offer.
So I came up with the following code:
SELECT
INSTR(foo.filepath, '/',1, LENGTH(foo.filepath) - LENGTH( REPLACE( foo.filepath, '/', ''))) AS IndexOfLastSlash
FROM foo
However, for my specific situation (being the OpenEdge (Progress) database) this did not result into the desired behaviour because replacing the character with an empty char gave the same length as the original string. This doesn't make much sense to me but I was able to bypass the problem with the code below:
SELECT
INSTR(foo.filepath, '/',1, LENGTH( REPLACE( foo.filepath, '/', 'XX')) - LENGTH(foo.filepath)) AS IndexOfLastSlash
FROM foo
Now I understand that this code won't solve the problem for T-SQL because there is no alternative to the INSTR function that offers the Occurence property.
Just to be thorough I'll add the code needed to create this scalar function so it can be used the same way like I did in the above examples. And will do exactly what the OP wanted, serve as a LastIndexOf method for SQL Server.
-- Drop the function if it already exists
IF OBJECT_ID('INSTR', 'FN') IS NOT NULL
DROP FUNCTION INSTR
GO
-- User-defined function to implement Oracle INSTR in SQL Server
CREATE FUNCTION INSTR (#str VARCHAR(8000), #substr VARCHAR(255), #start INT, #occurrence INT)
RETURNS INT
AS
BEGIN
DECLARE #found INT = #occurrence,
#pos INT = #start;
WHILE 1=1
BEGIN
-- Find the next occurrence
SET #pos = CHARINDEX(#substr, #str, #pos);
-- Nothing found
IF #pos IS NULL OR #pos = 0
RETURN #pos;
-- The required occurrence found
IF #found = 1
BREAK;
-- Prepare to find another one occurrence
SET #found = #found - 1;
SET #pos = #pos + 1;
END
RETURN #pos;
END
GO
To avoid the obvious, when the REVERSE function is available you do not need to create this scalar function and you can just get the required result like this:
SELECT
LEN(foo.filepath) - CHARINDEX('\', REVERSE(foo.filepath))+1 AS LastIndexOfSlash
FROM foo
Try this.
drop table #temp
declare #brokername1 nvarchar(max)='indiabullssecurities,canmoney,indianivesh,acumencapitalmarket,sharekhan,edelweisscapital';
Create Table #temp
(
ID int identity(1,1) not null,
value varchar(100) not null
)
INSERT INTO #temp(value) SELECT value from STRING_SPLIT(#brokername1,',')
declare #id int;
set #id=(select max(id) from #temp)
--print #id
declare #results varchar(500)
select #results = coalesce(#results + ',', '') + convert(varchar(12),value)
from #temp where id<#id
order by id
print #results

Remove a value from a comma separated string in sql stored procedure

I have a field that store the comma separated id's of publications. Such as 123456,2345678,123567,2345890 etc. When I pull the data from the database I put it into a json object and the web page loops the values and displays the data. Works great.
What I would like to do is to send the stored proc one of the numbers and the stored proc will remove it from the string and save it back to the table. Such as the end user worked on publication 123567 and now wants to make it completed, so I want to remove it from the string so they don't see it in the future. I have a split function in the database but I don't know how to wire it up to delete or rebuild the string without the publication ID.
I don't have any code to show because I am at a loss to start. I figure I need to pass the entire string and the ID. Split the string and loop each value to rebuild a new string but check if the ID is there and skip it.
Is this the best way to do this?
Thanks for your help
what I've ended up with as the base to work from is:
ALTER FUNCTION dbo.RemovePMID (
#S VARCHAR(MAX)
,#PMID VARCHAR(15)
)
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE #T VARCHAR(50)
DECLARE #W VARCHAR(50)
SET #T = ''
WHILE len(#S) > 0
BEGIN
SET #W = left(#S, charindex(',', #S + ',') - 1)
IF charindex(#W, + #PMID) = 0
SET #T = #T + ',' + #W
SET #S = stuff(#S, 1, charindex(',', #S + ','), '')
END
RETURN substring(#T, 2, len(#T) - 2)
END
GO
No need for loops (please take a peek at Larnu's suggestion for your parse/split function)
That said, consider the following
Example
Declare #S varchar(max) = '123456,2345678,123567,2345890'
Declare #Zap varchar(50)='123456'
Select reverse(stuff(reverse(stuff(replace(','+#S+',',','+#Zap+',',','),1,1,'')),1,1,''))
Returns
2345678,123567,2345890

SQL Server: how to remove leading 'A's from base64 string

I'm working on SQL Server and trying to create a single key combining data from bigint and string columns. To minimize the size of bigint's represented as strings I'm using Base 64 encoding. The problem is that the result includes leading 'A's meaning base64 zeroes and it increases the size of the resulting field. What is the way to remove these leading A using T-SQL or XQuery?
Sample code:
DECLARE #binInput VARBINARY(MAX)
SET #binInput = CAST(123 AS VARBINARY(MAX))
SELECT CAST(N'' AS XML).value('xs:base64Binary(sql:variable("#binInput"))', 'varchar(max)')
I have a resulting AAAAew== where I would prefer to see just ew because of the idea is to make the final string as short as it possible and base64 string should be shorter than base10.
update 1: as were suggested by Richard Boyce I tried to convert bigint to the equal string, but it gives null as a result of base64 conversion
declare #input bigint
declare #varInput nvarchar(max)
set #input = 123
set #varInput = cast(cast(#input as varbinary(max)) as varchar(max))
select CAST(N'' AS xml).value('xs:base64Binary(sql:variable("#varInput"))', 'varchar(max)')
update 2: the current solution is to get a base64binary string and to remove leading 'A's and trailing '='s. It's not perfect, so any suggestions are welcome. Actual code:
declare #input bigint
set #input = 1234567890
declare #output varchar(max)
set #output = (select cast(#input as varbinary(max)) for xml path(''),binary base64)
set #output = replace(ltrim(replace(#output,'A',' ')),' ','A') -- remove leading 'A's
set #output = replace(#output,'=','') -- remove trailing '='s
select #output
Rather than trying to remove leading "A's" from the encoded result look at preventing them in the first place.
You need to convert your number to a string before encoding.
Try this
DECLARE #binInput VARBINARY(MAX)
SET #binInput = CAST(CAST(123 AS VARCHAR(MAX)) AS VARBINARY(MAX))
DECLARE #Result VARCHAR(MAX)
SELECT #Result = CAST(N'' AS XML).value('xs:base64Binary(sql:variable("#binInput"))', 'varchar(max)')
SELECT CAST(CAST(N'' AS XML).value('xs:base64Binary(sql:variable("#Result"))', 'varbinary(max)') AS VARCHAR(MAX))
Note that when encoded "123" becomes "MTIz" not ew==
Not wanting to leave an answer that doesn't answer the question, here's how to remove a number of leading A's from a string (but the answer #Richard gave is better):
DECLARE #VAL NVARCHAR(MAX) = N'AAAA12345ABCD9876=='
SELECT SUBSTRING(#VAL,PATINDEX('%[^A]%',#VAL), LEN(#VAL))
----------------
12345ABCD9876==

Mistake in Sql query while splitting string

What mistake I am making in this sql query
Declare #str Varchar(100) = 'asasa,bsasas,csasa,dsczxvvc'
declare #d varchar(2)=','
SELECT
RIGHT(LEFT(#str,Number-1),
CHARINDEX(#d,REVERSE(LEFT(#d+#str,Number-1))))
FROM
master..spt_values
WHERE
Type = 'P' AND Number BETWEEN 1 AND LEN(#str)
AND SUBSTRING(#str,Number,1) = #d
Expected Result
(No column name)
asasa
bsasas
csasa
dsczxvvc
Actual Result
(No column name)
asasa
bsasas
csasa
Your AND SUBSTRING(#str, Number, 1) = #d is forcing a comma to be at the end of dsczxvvc...there isn't one. asasa,bsasas,csasa,dsczxvvc, works.
add one more comma at the end of string
you can directly add comma in the string like = "asasa,bsasas,csasa,dsczxvvc,"
or
handle this thing in sql side.
Declare #str Varchar(100)
set #str = 'asasa,bsasas,csasa,dsczxvvc'
declare #d varchar(2)
set #d =','
set #str = #str + ','
SELECT
RIGHT(LEFT(#str,Number-1),
CHARINDEX(#d,REVERSE(LEFT(#d+#str,Number-1))))
FROM
master..spt_values
WHERE
Type = 'P' AND Number BETWEEN 1 AND LEN(#str)
AND SUBSTRING(#str,Number,1) = #d
This is because since the last string portion does not have the seperator at the end of the string
If you add the following code just before the SELECT statement, it will work
set #str = #str + #d
There are many split functions on the web, you can use one of them actually.
Split string using CLR function
Split using XML
SQL Server split string function

Stored Procedure.. using sql server

Can any tell me how to send the LIst of IDs to the stored procedure in sql.
I need to send the List from My Controller so that that List of ID's can execute at a time using stored procedure.
Thanks
In SQL Server 2008 and up you can use Table-Valued Parameters
The best way (in 2008) is to pass it as a table. Pre 2008 you had to use a CSV format VarChar then split it out.
Have a read of this: http://www.sommarskog.se/arrays-in-sql-2008.html
What about a comma delimited string of Id's?
The problem is sql server doesn't support an array data type (or similar)
Sounds like you need something along the lines of this:
CREATE FUNCTION [dbo].[Split_String]
(
#ConcatValues VARCHAR(MAX)
)
RETURNS #Values Table
(
Value VARCHAR(MAX)
)
AS
/**************************************************************************************************************
Purpose: When called from a stored procedure and passed a character delimited parameter (of String data type values),
this function returns a table named "#Values" with a field named "Value" (populated with the parameter list)
which can then be referenced in the stored procedure.
This function requires that the delimited paramater have as its first character the delimiter character.
Sample calls:
Select * from [dbo].[Split_String](';dog;cat;mouse')
Select * from [dbo].[Split_String]('| dog| cat| mouse|')
Select * from [dbo].[Split_String]('|')
Select * from [dbo].[Split_String]('')
**************************************************************************************************************/
BEGIN
--Indexes to keep the position of searching
DECLARE #Delim CHAR(1)
Declare #Pos1 Int
Declare #Pos2 Int
--Identify delimiter character
SET #Delim = SUBSTRING(#ConcatValues, 1, 1)
--Append delimiter character
Set #ConcatValues = #ConcatValues + ' ' + #Delim
--Set 1st character of 1st value
Set #Pos2 = 2
While #Pos2 < Len(#ConcatValues)
BEGIN
Set #Pos1 = CharIndex(#Delim, #ConcatValues, #Pos2)
Insert #Values SELECT LTRIM(RTRIM(Substring(#ConcatValues, #Pos2, #Pos1 - #Pos2)))
--Go to next non-delimiter character
Set #Pos2 = #Pos1 + 1
END
RETURN
END
GO
Our split function is generic for use in a wide variety of situations and is dependent on the delimiter being identified by the first character in the string. It is likely that it could be simplified a bit if you only need it in one spot.

Resources