"String or binary data would be truncated." for NVARCHAR but not VARCHAR in LIKE operation - sql

In SQL Server, nvarchar takes twice the space of varchar, and its pre-page-pointer limit is 4000 compared to varchar's 8000.
So, why does the following like comparison give a String or binary data would be truncated. error...
select 1 where '' like cast(replicate('x', 4001) as nvarchar(max))
...while casting as a massively larger varchar does not?
select 1 where '' like cast(replicate('x', 123456) as varchar(max))
In fact, why does the top live give a truncation error at all when it's clearly declared as nvarchar(max) which has a size limit of about 2GB?

From the description of the LIKE operator:
pattern
Is the specific string of characters to search for in
match_expression, and can include the following valid wildcard
characters. pattern can be a maximum of 8,000 bytes.
This query shows a factual count of symbols:
select len(replicate('x', 123456)) as CntVarchar,
len(replicate('x', 4001)) as CntNVarchar
+------------+-------------+
| CntVarchar | CntNVarchar |
+------------+-------------+
| 8000 | 4001 |
+------------+-------------+
The first case has 8000 bytes. The second has 8002 bytes, that violates the rule "can be a maximum of 8,000 bytes".

Related

Additional 0 in varbinary insert in SSMS

I have a problem when I am trying to move a varbinary(max) field from one DB to another.
If I insert like this:
0xD0CF11E0A1B11AE10000000
It results the beginning with an additional '0':
0x0D0CF11E0A1B11AE10000000
And I cannot get rid of this. I've tried many tools, like SSMS export tool or BCP, but without any success. And it would be better fro me to solve it in a script anyway.
And don't have much kowledge about varbinary (a program generates it), my only goal is to copy it:)
0xD0CF11E0A1B11AE10000000
This value contains an odd number of characters. Varbinary stores bytes. Each byte is represented by exactly two hexadecimal characters. You're either missing a character, or your not storing bytes.
Here, SQL Server is guessing that the most significant digit is a zero, which would not change the numeric value of the string. For example:
select 0xD0C "value"
,cast(0xD0C as int) "as_integer"
,cast(0x0D0C as int) "leading_zero"
,cast(0xD0C0 as int) "trailing_zero"
value 3_char leading_zero trailing_zero
---------- --------- --------------- ----------------
0d0c 3340 3340 53440
Or:
select 1 "test"
where 0xD0C = 0x0D0C
test
-------
1
It's just a difference of SQL Server assuming that varbinary always represents bytes.

How to do a count of fields in SQL with wrong datatype

I am trying to import legacy data from another system into our system. The problem I am having is that the legacy data is dirty- very dirty! We have a field which should be an integer, but sometimes is a varchar, and the field is defined as a varchar...
In SQL Server, how can I do a select to show those records where the data is varchar instead if int?
Thanks
If you want to find rows1 where a column contains any non-digit characters or is longer than 9 characters (either condition means that we cannot assume it would fit in an int, use something like:
SELECT * FROM Table WHERE LEN(ColumnName) > 9 or ColumnName LIKE '%[^0-9]%'
Not that there's a negative in the LIKE condition - we're trying to find a string that contains at least one non-digit character.
A more modern approach would be to use TRY_CAST or TRY_CONVERT. But note that a failed conversion returns NULL and NULL is perfectly valid for an int!
SELECT * FROM Table WHERE ColumnName is not null and try_cast(ColumnName as int) is null
ISNUMERIC isn't appropriate. It answers a question nobody has ever wanted to ask (IMO) - "Can this string be converted to any of the numeric data types (I don't care which ones and I don't want you to tell me which ones either)?"
ISNUMERIC('$,,,,,,,.') is 1. That should tell you all you need to know about this function.
1If you just want a count, as per the title of the question, then substitute COUNT(*) for *.
In SQL Server, how can I do a select to show those records where the data is varchar instead of int?
I would do it like
CREATE TABLE T
(
Data VARCHAR(50)
);
INSERT INTO T VALUES
('102'),
(NULL),
('11Blah'),
('5'),
('Unknown'),
('1ThinkPad123'),
('-11');
SELECT Data -- Per the title COUNT(Data)
FROM
(
SELECT Data,
cast('' as xml).value('sql:column("Data") cast as xs:int ?','int') Result
FROM T --You can add WHERE Data IS NOT NULL to exclude NULLs
) TT
WHERE Result IS NULL;
Returns:
+----+--------------+
| | Data |
+----+--------------+
| 1 | NULL |
| 2 | 11Blah |
| 3 | Unknown |
| 4 | 1ThinkPad123 |
+----+--------------+
That if you can't use TRY_CAST() function, if you are working on 2012+ version, I'll recommend that you use TRY_CAST() function like
SELECT Data
FROM T
WHERE Data IS NOT NULL
AND
TRY_CAST(Data AS INT) IS NULL;
Demo
Finally, I would say do not use ISNUMERIC() function because of (from docs) ...
Note
ISNUMERIC returns 1 for some characters that are not numbers, such as plus (+), minus (-), and valid currency symbols such as the dollar sign ($). For a complete list of currency symbols, see money and smallmoney (Transact-SQL).

SQL Server size difference for a column

I have table in SQL Server say "Temp" and it has Addr1, Addr2, Addr3, Addr4 columns and some additional columns also there.
These Addr1, Addr2, Addr3 and Addr4 are nvarchar type. when I check the size of this column by object explorer. it shows all of them in nvarchar(100).
But when I check them using Alt + F1. It shows the details in Result Pane with the length as 200. screenshot is below.
why there is different?
If I enter more than 100 characters, I'm getting truncation errors? seems like it taking only 100 characters.
can you please let me know what is the length value specifies ?
Thanks,
Prakash.
Because the size listed in Object Explorer is number of characters and the size listed in the result of your query to sp_help is number of bytes.
VARCHAR values in SQL use 1 byte per character, whereas NVARCHAR values use 2 bytes per character. Both also need a 2 byte overhead - see below. So because you are looking at NVARCHAR columns, these need 200 (well actually 202) bytes to store 100 characters, where a VARCHAR would only require 100 (really 102).
References:
MSDN: char and varchar
The storage size is the actual length of the data entered + 2 bytes.
MSDN: nchar and nvarchar:
The storage size, in bytes, is two times the actual length of data entered + 2 bytes.
(emphasis mine)
MSDN: sp_help:
Reports information about a database object (any object listed in the sys.sysobjects compatibility view), a user-defined data type, or a data type.
/------------------------------------------------------------------------\
| Column name | Data type | Description |
|-------------+-----------+----------------------------------------------|
| Length | smallint | Physical length of the data type (in bytes). |
\------------------------------------------------------------------------/

SQL SERVER: String or binary data would be truncated. nvarchar

I'm trying to insert into the following table:
but for some reason I cannot insert more than 250 characters into slabel1 field, even though it's size it's 500. Every time this happens I receive the following error:
String or binary data would be truncated. The statement has been
terminated.
I do not understand why.
Your results show the length in bytes of the column, not how many characters it can store. The column you are using is an nvarchar column, and so a character will take up 2 bytes instead of 1, so in your case (500 / 2) = 250 characters max.
This will show you the difference, we have two columns, each which can hold 50 characters, but the length of the nvarchar column is 100
CREATE TABLE [#text]
(
[Text] VARCHAR(50),
[NText] NVARCHAR(50)
)
SELECT COL_LENGTH( 'tempdb..#Text' , 'Text' ) [Varchar_Length],
COL_LENGTH( 'tempdb..#Text' , 'NText' ) [NVarchar_Length]
DROP TABLE [#text]
The results are:
Varchar_Length | NVarchar_Length
50 | 100
Because it's NVARCHAR
nchar and nvarchar
nchar [ ( n ) ]
Fixed-length Unicode string data. n defines the string
length and must be a value from 1 through 4,000. The storage size is
two times n bytes. When the collation code page uses double-byte
characters, the storage size is still n bytes. Depending on the
string, the storage size of n bytes can be less than the value
specified for n. The ISO synonyms for nchar are national char and
national character..
nvarchar [ ( n | max ) ]
Variable-length Unicode string data. n
defines the string length and can be a value from 1 through 4,000. max
indicates that the maximum storage size is 2^31-1 bytes (2 GB). The
storage size, in bytes, is two times the actual length of data entered
+ 2 bytes. The ISO synonyms for nvarchar are national char varying and national character varying.
Try this one to see the differences
DECLARE #text1 NVARCHAR(200)
DECLARE #text2 VARCHAR(200)
SET #text1 = 'aaaaaaaa'
SET #text2 = 'aaaaaaaa'
SELECT LEN(#text1), DATALENGTH(#text1)
SELECT LEN(#text2), DATALENGTH(#text2)

What data type to be used for description of an object?

A table has a field of description in sql server. If I take varchar then its maximum limit is 8000 characters but a description can be larger than that. I am using this field for a job description which are normally lengthy .
A varchar(max) has no (effective) limit. Use that.
Use VARCHAR(MAX). It can store more than 8k chars. Actually it can store up to 2GB
varchar [ ( n | max ) ]
Variable-length, non-Unicode string data. n defines the string length and can be a value from 1 through 8,000. MAX indicates that the maximum storage size is 2^31-1 bytes (2 GB). The storage size is the actual length of the data entered + 2 bytes. The ISO synonyms for varchar are char varying or character varying.
Read more at http://msdn.microsoft.com/en-us/library/ms176089.aspx
Please note, that the TEXT and NTEXT types can store nearly the same amount of data, but they are obsolete and you can do less operations on them. Use VARCHAR(MAX) and NVARCHAR(MAX) instead of TEXT and NTEXT.
You can use
varchar(max) or Text data type.