Detecting cells in column that cause error in SQL - sql

Assuming that we are trying to alter the type of a column in a SQL table, say from varchar to float, using: ALTER TABLE <mytable. ALTER COLUMN <mycolumn> FLOAT. However, we get the error Error to convert datatype varchar to float.
Is it possible to narrow down the cells in the column that are causing this problem?
Thanks,

You can use the ISNUMERIC function:
select * from table where isnumeric(mycolumn) = 0
If you allow NULL values in your column, you'll also need to add a check for NULLs since ISNUMERIC(NULL) evaluates to 0 as well
select * from table where isnumeric(mycolumn) = 0 or mycolumn is not null

I have encounter the same issue while writing ETL procedure. moving staging data into actual core table and we had all columns on staging table a NVARCHAR.
there could be a numeric value which is either scientific format (like very large float values in Excel cell) or it has one of this special CHAR in it. ISNUMERIC function evaluates this char as True when it is appear as whole value.
for example
SELECT ISUMERIC('$'), ISNUMERIC('.')
so just check if any of cell in that column has such values.
'$'
'-'
'+'
','
'.'
if you find that cell has one of above then just exclude such data in your query.
if you find that you have data in scientific format like "1.2408E+12" then ISNUMERIC will be still evaluate it as TRUE but straight insert will fail so convert in appropriate numeric format.
DECLARE #t NUMERIC(28,10)
SELECT #t=CONVERT(NUMERIC(28,10),CONVERT(FLOAT,'1.2408E+12'))
SELECT #t

Dirty, but effective. This removes all characters found in floats (#s and decimal - I'm US-centric). The result you get from the query are items that would need to be reviewed to determine what should be done (ie the cells causing you problems).
SELECT
*
FROM (
SELECT
TableId
, REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
ISNULL(Col1,'')
,'0','')
,'1','')
,'2','')
,'3','')
,'4','')
,'5','')
,'6','')
,'7','')
,'8','')
,'9','')
,'.','') [FilteredCol1]
FROM Table
) a
WHERE len(a.[FilteredCol1])>0

Select any records where the varchar value contains any non-numeric characters
SELECT col
FROM tab
WHERE col LIKE '%[^0-9.]%'
and any rows that might have more than one period:
SELECT col
FROM tab
WHERE col LIKE '%.%.%'

Related

How to convert or cast int to string in SQL Server

Looking at a column that holds last 4 of someone's SSN and the column was originally created as an int datatype. Now SSN that begin with 0 get registered as 0 on the database.
How can I convert the column and it's information from an int into a string for future proof?
You should convert. CONVERT(VARCHAR(4), your_col)
If you specifically want zero-padded numbers, then the simplest solution is format():
select format(123, '0000')
If you want to fix the table, then do:
alter table t alter column ssn4 char(4); -- there are always four digits
Then update the value to get the leading zeros:
update t
ssn4 = format(convert(int, ssn4), '0000');
Or, if you just want downstream users to have the string, you can use a computed column:
alter table t
add ssn4_str as (format(ssn4, '0000'));
If you want to add leading zeros, use:
SELECT RIGHT('0000'+ISNULL(SSN,''),4)
First thing never store SSN or Zip Code as any numeric type.
Second you should fix the underlying table structure not rely on a conversion...but if you're in a jam this is an example of a case statement that will help you.
IF OBJECT_ID('tempdb..#t') IS NOT NULL
BEGIN
DROP TABLE #t
END
GO
CREATE TABLE #t(
LastFourSSN INT
)
INSERT INTO #t(LastFourSSN)
VALUES('0123'),('1234')
SELECT LastFourSSN --strips leading zero
FROM #t
SELECT -- adds leading zero to anything less than four charaters
CASE
WHEN LEN(LastFourSSN) < 4
THEN '0' + CAST(LastFourSSN AS VARCHAR(3))
ELSE CAST(LastFourSSN AS VARCHAR(4))
END LastFourSSN
FROM #t
If you are looking for converting values in the column for your purpose to use in application, you can use this following-
SELECT CAST(your_column AS VARCHAR(100))
--VARCHAR length based on your data
But if you are looking for change data type of your database column directly, you can try this-
ALTER TABLE TableName
ALTER COLUMN your_column VARCHAR(200) NULL
--NULL or NOT NULL based on the data already stored in database

Spaces in WHERE clause for SQL Server [duplicate]

This question already has answers here:
Why the SQL Server ignore the empty space at the end automatically?
(2 answers)
Closed 4 years ago.
I want to find out the records in which a certain column contains exactly one space and nothing else. So I wrote the first of the following queries:
select COUNT(*)
from mytable
where col = ' ' -- One space
select COUNT(*)
from mytable
where col = ' ' -- Two spaces
select COUNT(*)
from mytable
where col = ' ' -- Three spaces
However, all three queries return the exact same records. Does Microsoft SQL Server not distinguish between the amount of spaces? How can I query exactly for one, two or more spaces?
Yes, it ignores trailing spaces in comparisons.
You can try to append a delimiting character.
SELECT count(*)
FROM mytable
WHERE col + 'X' = ' X';
You can combine DATALENGTH clause with your query:
select COUNT(*)
from mytable
where col = ' '
and DATALENGTH(col) = 1
The link posted by Ivan Starostin in the comments of the OP provides a good explanation and I think it deserves a full answer instead of just a comment.
To summarize, try using LIKE instead of equality:
select COUNT(*)
from mytable
where col LIKE ' ' -- one space
And you can also use DATALENGTH to calculate how many bytes are in the field to double-check field length:
select col, DATALENGTH(col)
from mytable;
Please note that DATALENGTH will return a different value if col is a VARCHAR vs NVARCHAR. VARCHAR stores each character as 1 byte where NVARCHAR stores each character as 2 bytes since NVARCHAR is stored in Unicode.
You can replace the single space with a single character (for exampe §) and then put this character in your where condition:
declare #tmp table(col varchar(50))
insert into #tmp values
(' '),
(' '),
(' ')
select COUNT(*) as one_space_count
from #tmp
where replace(col,' ','§')='§'
select COUNT(*) as two_space_count
from #tmp
where replace(col,' ','§')='§§'
select COUNT(*) as three_space_count
from #tmp
where replace(col,' ','§')='§§§'
Results:

� IN SQL Server database

in my database I have this char �. I want to locate them with a query
Select *
from Sometable
where somecolumn like '%�%'
this gets me no result.
I think it is ANSI encoding
use N like below
where col like N'%�%'
why do you think ,you need N prefix:
Prefix Unicode character string constants with the letter N. Without the N prefix, the string is converted to the default code page of the database. This default code page may not recognize certain characters.
Thanks to Martin Smith,Earlier i tested only with one character earlier and it worked,but as Martin pointed out, it returns all characters..
Below query works and returns only intended
select * from #demo where id like N'%�%'
COLLATE Latin1_General_100_BIN
Demo:
create table #demo
(
id nvarchar(max)
)
insert into #demo
values
(N'ﬗ'),
( N'�')
to know more about unicode,please see below links
http://kunststube.net/encoding/
https://www.joelonsoftware.com/2003/10/08/the-absolute-minimum-every-software-developer-absolutely-positively-must-know-about-unicode-and-character-sets-no-excuses/
This is the Unicode replacement character symbol.
It could match any of 2,048 invalid code points in the UCS-2 encoding (or the single character U+FFFD for the symbol itself).
You can use a range and a binary collate clause to match them all (demo).
WITH T(N)
AS
(
SELECT TOP 65536 NCHAR(ROW_NUMBER() OVER (ORDER BY ##SPID))
FROM master..spt_values v1,
master..spt_values v2
)
SELECT N
FROM T
WHERE N LIKE '%[' + NCHAR(65533) + NCHAR(55296) + '-' + NCHAR(57343) + ']%' COLLATE Latin1_General_100_BIN
You can use ASCII to find out the ascii code for that char
Select ascii('�')
And use CHAR to retrieve the char from that code and combine it in a LIKE expression
Select * from Sometable
where somecolumn like '%'+CHAR(63)+'%'
Note the collation you use can affect the result. Also it depends on the encoding used by your application to feed your data (UTF-8, UNICODE, etc). also how you store it VARCHAR, or NVARCHAR has a last say on what you see.
There's more here in this similar question
EDIT
#Mark
try this simple test:
create table sometable(somecolumn nvarchar(100) not null)
GO
insert into sometable
values
('12345')
,('123�45')
,('12345')
GO
select * from sometable
where somecolumn like '%'+CHAR(63)+'%'
GO
This only means that character was stored win the as a "?" in this test.
When you see a � it means the app where you are seeing isn't quite sure what to print out.
It also mean OP probably needs to find out what char is that using a query.
Also note it means a string outputted like ��� can be 3 formed by different characters.
CHAR(63) was just an example, but you are right this in the ASCII table will be a standard interrogation.
EDIT
#Bridge
Not with time right now to deep dig in it but the below test don't worked
Select ascii('�'), CHAR(ascii('�')), UNICODE(N'�'), CHAR(UNICODE(N'�'))
GO
create table sometable(somecolumn nvarchar(100) not null)
GO
insert into sometable
values
('12345')
,('123�45')
,('12345')
,('12'+NCHAR(UNICODE(N'�'))+'345')
GO
select * from sometable
where somecolumn like '%'+CHAR(63)+'%'
select * from sometable
where somecolumn like '%'+NCHAR(UNICODE(N'�'))+'%'
GO

SQL Server : Nvarchar to Varchar

I have a table with two columns, one is of type Varchar and the other in NVarchar.
I want to update all the rows so VarcharField = NVarcharField.
It won't let me because some of the rows contain chars that are not allowed in varchar column with the current code page.
How can I find these rows?
Is it possible to remove any char that doesn't fit the specific code page I'm using?
SQL Server 2012.
You can find the rows by attempting to convert the nvarchar() col to varchar():
select nvarcharcol
from t
where try_convert(varchar(max), nvarcharcol) is null;
Try this..
to find the rows with values that are not supported by varchar
declare #strText nvarchar(max)
set #strText = 'Keep calm and say தமிழன்டா'
select cast(#strText as varchar(max)) col1 , N'Keep calm and say தமிழன்டா' col2
Here #strText has non-english chars, When you try to cast that into varchar the non-english chars turns into ????. So the col1 and col2 are not equal.
select nvar_col
from tabl_name
where nvar_col != cast(nvar_col as varchar(max))
Is it possible to remove any char that doesn't fit the specific code page I'm using?
update tabl_name
set nvar_col = replace(cast(nvar_col as varchar(max)),'?','')
where nvar_col != cast(nvar_col as varchar(max))
Replace ? with empty string and update them.
If Gordon's approach doesn't work because you get question marks from TRY_CONVERT instead of the expected NULL, try this approach:
SELECT IsConvertible = CASE WHEN NULLIF(REPLACE(TRY_CONVERT(varchar(max), N'人物'), '?',''), '') IS NULL
THEN 'No' ELSE 'Yes' END
If you need it as filter for the rows that can't be converted:
SELECT t.*
FROM dbo.TableName t
WHERE NULLIF(REPLACE(TRY_CONVERT(varchar(max), t.NVarcharField), '?',''), '') IS NULL

using trim in a select statement

I have a table, my_table, that has a field my_field. myfield is defined as VARCHAR(7). When I do:
SELECT myfield
FROM my_table;
I get what appears to be the entire 7 characters, but I only want the actual data.
I tried:
SELECT TRIM(myfield)
FROM my_table;
and several variations. But instead of getting 'abcd', I get 'abcd '.
How do I get rid of the trailing blanks?
As others have said:
trim whitespace before data enters the database ("Mop the floor...);
ensure this is not actually a column of type CHAR(7).
Additionally, add a CHECK constraint to ensure no trailing spaces ("...fix the leak.") While you are at it, also prevent leading spaces, double spaces and zero-length string e.g.
CREATE TABLE my_table
(
myfield VARCHAR(7) NOT NULL
CONSTRAINT myfield__whitespace
CHECK (
NOT (
myfield = ''
OR myfield LIKE ' %'
OR myfield LIKE '% '
OR myfield LIKE '% %'
)
)
);-
VARCHAR columns will not pad the string you insert, meaning if you are getting 'ABCD ', that's what you stored in the database. Trim your data before inserting it.
Make sure you are not using the CHAR datatype, which will pad your data in the way you suggest. In any case:
SELECT TRIM(myfield) FROM mytable;
will work.
Make sure also that you are not confusing the way the SQL interpreter adds padding chars to format the data as a table with the actual response.
Make sure that you are not inserting data in this column from a CHAR(7) field.
You need to trim your result when selecting as opposed to when inserting, eg:
SELECT TRIM(myfield) FROM my_table;