The select datalength(cast('12345' as nvarchar)) query returns 10 (this is OK), but
declare #string as nvarchar
set #string = cast('12345' as nvarchar)
select datalength(#string)
returns 2 instead of 10. Why? How can I use DATALENGHT() for determining the datalength of a string stored in a variable?
Always specify the length n of character data. eg
declare #string as nvarchar(30)
set #string = cast('12345' as nvarchar(30))
select datalength(#string)
The behavior if you don't is described in the docs:
When n is not specified in a data definition or variable declaration
statement, the default length is 1. When n is not specified with the
CAST function, the default length is 30.
nchar and nvarchar
Related
I saw the below syntax in a training video and I was wondering what this is called and which methods can we use on a variable?
DECLARE #text VARCHAR(max);
SET #text = REPLICATE(CAST('asdfasdf' as varchar(max)),8000);
SET #text.write('zzzzzzzz',0,8);
SELECT #text
the value stored in the variable is
'zzzzzzzzasdfasdf...'
The update.write syntax is not really a method. It is a TSQL syntax for updating large data types like nvarchar(max).
The official UPDATE documentation describes how to use .WRITE.
SET
{ column_name = { expression | DEFAULT | NULL }
| { udt_column_name.{ { property_name = expression
| field_name = expression }
| method_name ( argument [ ,...n ] )
}
}
| column_name { .WRITE ( expression , #Offset , #Length ) }
.WRITE (expression,#Offset,#Length) Specifies that a section of the
value of column_name is to be modified. expression replaces #Length
units starting from #Offset of column_name. Only columns of
varchar(max), nvarchar(max), or varbinary(max) can be specified with
this clause. column_name cannot be NULL and cannot be qualified with a
table name or table alias.
expression is the value that is copied to column_name. expression must
evaluate to or be able to be implicitly cast to the column_name type.
If expression is set to NULL, #Length is ignored, and the value in
column_name is truncated at the specified #Offset.
#Offset is the starting point in the value stored in column_name at
which expression is written. #Offset is a zero-based ordinal byte
position, is bigint, and cannot be a negative number. If #Offset is
NULL, the update operation appends expression at the end of the
existing column_name value and #Length is ignored. If #Offset is
greater than the byte length of the column_name value, the Database
Engine returns an error. If #Offset plus #Length exceeds the end of
the underlying value in the column, the deletion occurs up to the last
character of the value.
#Length is the length of the section in the column, starting from
#Offset, that is replaced by expression. #Length is bigint and cannot
be a negative number. If #Length is NULL, the update operation removes
all data from #Offset to the end of the column_name value.
See also Updating Large Data Types and the examples provided for updating large data types.
It's not a method, though it sure looks like it. Unlike for example XML methods, which you can use in a SELECT, this is a mutator. It's available on (n)varchar and varbinary data types with max length specified, and is used to modify the stored values efficiently.
There's not much information about them out there, I only found this blog post.
DECLARE #ID VARCHAR
PRINT #ID
SELECT #ID=CAST(10 AS VARCHAR)
PRINT #ID
SELECT #ID
returns *
why ?
In varchar(n/max) when n is not specified in a data definition or variable declaration statement, the default length is 1. That's why returning *(only single value).
I've declared a variable in a stored procedure:
DECLARE #CurrentChunk NVARCHAR(250)
I would like to use the length of the variable, i.e. 250, later in my sp for computational purposes, and I want to keep my code as dry as possible.
Here's my code (assume #Narrative is a param to the SP):
DECLARE #ChunkSizeCharacters INT,
#NumChunks INT,
#LoopIndex INT,
#CurrentChunk NVARCHAR(250)
SET #ChunkSizeCharacters = 250 -- HERE'S WHERE I WANT THE LENGTH OF #CurrentChunk
SET #NumChunks = CEILING((LEN(#Narrative) * 1.0)/#ChunkSizeCharacters)
SET #LoopIndex = 0;
WHILE (#LoopIndex < #NumChunks)
BEGIN
SET #CurrentChunk = SUBSTRING(#Narrative,
((#LoopIndex * #ChunkSizeCharacters) + 1), #ChunkSizeCharacters)
INSERT INTO [dbo].[Chunks] ([Chunk]) VALUES (#CurrentChunk)
SET #LoopIndex = #LoopIndex + 1
END
Is there a way to ascertain the length of an NVARCHAR or VARCHAR variable definition (please read carefully -- I'm not looking for LEN())?
It seems the MaxLength variant property returns the value you're looking for.
DECLARE #Banana varchar(255) = 'This banana'
SELECT SQL_VARIANT_PROPERTY(#Banana, 'MaxLength')
Returns 255.
If you don't mind overwriting the variable (and if you do, you can assign it to a temp NVARCHAR(MAX)):
SELECT #CurrentChunk = REPLICATE(0, 8000);
SELECT #ChunkSizeCharacters = LEN(#CurrentChunk);
This trick does not and cannot work for NVARCHAR(MAX), but that's presumably no problem, given it's enormous maximum size.
Unfortunately T-SQL has nothing in the way of metadata properties for variables. Even determining the type of an expression is a chore.
Interestingly, the value returned by that SELECT SQL_VARIANT_PROPERTY statement doesn't select into a plain, predefined variable. In the end, I used:
DECLARE #Text VARCHAR(400), #TextLen INT
SELECT #TextLen = CAST(SQL_VARIANT_PROPERTY(ISNULL(#Text, ''), 'MaxLength') AS INT)
Works like a charm for me!
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);
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.