April 3, 2009 at 3:22 pm
Hi All,
I have a table with CHAR data type. It has data with empty strings, one space and regular data.
I need to find the records with one_space (NOT empty string).
Here is the DDL.
create table t1 (col char(5))
Go
insert t1 select 'abc'
insert t1 select ''
insert t1 select ' ' -- one space
Apparently I can not use DATALENGTH (which gives 5) or len (which gives 0). Looks like SQL is truncating the cell values before applying these functions.
I can use VARCHAR column data type or some character to replace the empty_string. However the data is already exist in the table. And I need a SELECT on the existing table. Thanks..
April 4, 2009 at 1:02 am
Hello,
Is the Column in your Table set as “Not Null“ or “ANSI_Padding On”?
In either of these cases you will have problems because the data will have been padded with trailing spaces when inserted into the column i.e. a Single Space and an Empty String will both be stored identically. I suspect this is the case as you mentioned the DataLength function is returning 5.
To quote BOL “The char data type is a fixed-length data type when the NOT NULL clause is specified. If a value shorter than the length of the column is inserted into a char NOT NULL column, the value is right-padded with blanks to the size of the column. If ANSI_PADDING is ON when a char NULL column is created, it behaves the same as a char NOT NULL column: values are right-padded to the size of the column.”
Regards,
John Marsh
www.sql.lu
SQL Server Luxembourg User Group
April 4, 2009 at 9:13 am
Very good info on the Ansi-Padding and how CHAR columns respond, John...
It's still not going to help for this problem, though, because empty strings (in T-SQL) are never empty in a table. It's one of those things to avoid at design time. In Oracle, empty strings are stored as NULL. Same should be done here.
set ansi_padding OFF
drop table t1
create table t1 (RowNum INT IDENTITY(1,1), col char(5) NULL)
Go
insert t1 select 'abc'
insert t1 select ''
insert t1 select ' ' -- one space
SELECT DATALENGTH(COL),* FROM t1
WHERE Col = ' '
--Jeff Moden
Change is inevitable... Change for the better is not.
April 4, 2009 at 10:23 am
Thanks for your response... I tried this as below..
use testdb
go
set ansi_padding OFF
--drop table t1
create table t1 (RowNum INT IDENTITY(1,1), col char(5) NULL)
Go
insert t1 select 'abc'
insert t1 select ''
insert t1 select ' ' -- one space
SELECT DATALENGTH(COL) FROM t1
Result
-----------
3
1
1
So, second row gives 1 as a result whereas there is actually no space between quotes. It should give 0....
April 4, 2009 at 9:18 pm
apat (4/4/2009)
So, second row gives 1 as a result whereas there is actually no space between quotes. It should give 0....
That's what I was saying... you cannot get what you want because you can't actually store an empty string in a table.
--Jeff Moden
Change is inevitable... Change for the better is not.
April 4, 2009 at 11:17 pm
By putting varchar instead of char, it started handling blank and single space properly. But it is not recognizing between single space and more than one space.
set ansi_padding OFF
drop table t1
create table t1 (RowNum INT IDENTITY(1,1), col varchar(5) NULL)
Go
insert t1 select 'abc'
insert t1 select ''
insert t1 select ' ' -- one space
insert t1 select ' ' -- two space
SELECT * FROM t1
WHERE Col = ' ' and DATALENGTH(col)=1
April 5, 2009 at 1:08 am
Boolean_z,
Set ANSI_PADDING ON and your life will improve measurably 😉
Books Online
In a future version of SQL Server ANSI_PADDING will always be ON and any applications that explicitly set the option to OFF will produce an error. Avoid using this feature in new development work, and plan to modify applications that currently use this feature.
Books Online
We recommend that ANSI_PADDING always be set to ON.
See the entry under "SET ANSI_PADDING (Transact-SQL)"
Jeff Moden (4/4/2009)
That's what I was saying... you cannot get what you want because you can't actually store an empty string in a table.
*ahem*
SET ANSI_PADDING ON;
CREATE TABLE dbo.[50197629-3B44-40C6-9041-E6F579953DD9]
(
row_idINTEGER IDENTITY(1,1) PRIMARY KEY CLUSTERED,
testVARCHAR(55) NOT NULL
);
INSERTdbo.[50197629-3B44-40C6-9041-E6F579953DD9] (test) VALUES ('');
INSERTdbo.[50197629-3B44-40C6-9041-E6F579953DD9] (test) VALUES (CHAR(32));
INSERTdbo.[50197629-3B44-40C6-9041-E6F579953DD9] (test) VALUES (CHAR(32) + CHAR(32));
SELECTrow_id,
DATALENGTH(test) AS [datalength],
LEN(test) AS [len],
REPLACE(test, CHAR(32), 'X') AS [replace],
ASCII(test) AS [ascii]
FROMdbo.[50197629-3B44-40C6-9041-E6F579953DD9];
DROP TABLE dbo.[50197629-3B44-40C6-9041-E6F579953DD9];
-- Spot the difference!
row_id, datalength, len, replace, ascii
100NULL
210X32
320XX32
Paul White
SQLPerformance.com
SQLkiwi blog
@SQL_Kiwi
April 5, 2009 at 11:12 am
I stand corrected. Thanks for the code.
I'd be curious to know why anyone would want to use the difference between an empty string and a sting of 1 or more spaces as criteria for anything. I'd also be curious why anyone would want to use a fixed length datatype for something with a widely variable length like Microsoft did with the NVARCHAR(128) columns present in the SysProcesses table. Something similar to that caused a log table to contain about 94 gigabytes at work. After removing all of the trailing spaces, the size of that log went down to about 36 gigabytes.
--Jeff Moden
Change is inevitable... Change for the better is not.
April 5, 2009 at 2:48 pm
Hey Jeff,
I'm with you on the 'why use an empty string or spaces as criteria' thing; although I guess there is some wild and wacky legacy code out there. Unless something is explicitly forbidden by the laws of nature, it'll exist somewhere!
The fixed length columns in sysprocesses is an interesting one. I can only suppose that it was important that all the columns in that table had a fixed offset in the row, maybe for deep dark internal performance reasons...?
As an aside, I find myself very rarely using fixed-length types like CHAR or NCHAR in my tables. The behaviours with and without ANSI_PADDING set are just plain odd to my mind. The sooner all the ANSI standard settings are, er, standardised the better though. The number of times I've not been able to create an indexed view, persist a computed column, or whatever because of odd SETtings....well!
Paul
Paul White
SQLPerformance.com
SQLkiwi blog
@SQL_Kiwi
April 5, 2009 at 7:59 pm
Heh... ok... understood. And absolutely spot-on with the rest of what you said. Thanks, Paul. And good "meeting" you.
--Jeff Moden
Change is inevitable... Change for the better is not.
April 6, 2009 at 2:32 am
Jeff Moden (4/5/2009)
Heh... ok... understood. And absolutely spot-on with the rest of what you said. Thanks, Paul. And good "meeting" you.
Thanks Jeff - and you too! 🙂
Paul White
SQLPerformance.com
SQLkiwi blog
@SQL_Kiwi
April 6, 2009 at 8:33 am
Thanks everyone for your inputs...
Viewing 12 posts - 1 through 11 (of 11 total)
You must be logged in to reply to this topic. Login to reply