Cast / convert a column but getting error - sql-server

I have a column in database table defined as varchar(1000) null
In one of the situations, the data is entered as N/A - so I can force to ignore all values and use null.
But there are some values which I want to use.
If I use cast, convert, try_cast, tryconvert, to varchar all fails, but if I do it to int, it works, but the try cast, try convert works.
I am not sure why it is failing when I use try_cast and it says:
convert failed to convert N/A value to int.
Even I am not converting it to INT

Try the following:
DECLARE #test_val AS varchar(100) = 'N/A'
SELECT TRY_CAST(#test_val AS int)
This gives a result of NULL
DECLARE #test_val AS varchar(100) = '3'
SELECT TRY_CAST(#test_val AS int)
Gives a result of 3.
It may be that your SQL has a syntax error.

Related

SQL isnull fails with try_cast

I am trying to handle some data in the following way.
If the entry is numeric, cast it as an integer.
If the entry is not numeric, keep it as it is.
I am using 'try_cast' to cast my numeric entries to my integers. This gives NULL if the entry is not numeric.
declare #code varchar(3) = 'fff'
select try_cast(#code as int) as code
I then thought, well if I catch the null with an isnull I will be able to output the original value as I wanted.
declare #code varchar(3) = 'fff'
select isnull( try_cast(#code as int), #code) as code
However I get a conversion failed error.
I did not expect this behavior. Why is this happening and how can I acheive the desired behaviour?
TRY_CAST(... as int) return INT data type,
ISNULL(INT, VARCHAR(3)) leads both to INT
ISNULL: Returns the same type as check_expression.
declare #code varchar(3) = '123'
select ISNULL(CAST(try_cast(#code as int) as VARCHAR(3)),#code ) as code
may use
COALESCE: Returns the data type of expression with the highest data type
precedence
but INT upper VARCHAR in
Data type precedence
You are having a type-conversion error, because of the incompatibility. The column is either an integer or a string, but not both.
When you have two types in an expression, the numeric one dominates. In other words, SQL Server attempts to convert the string value to a number. Of course, this fails when done implicitly when try_convert() fails.
I would suggest two columns:
select try_cast(#code as int) as int_code, #code as orig_code
This is a block of code within a larger body of code, yes? As in, you're not trying to have a function dynamically return different data types based on the input?
If so, can you use sql_variant_property via an if-else block to direct flow of control? e.g.
declare #code varchar(3) = 'fff'
if SQL_VARIANT_PROPERTY(#code,'BaseType') = 'INT'
begin
print 'do numeric comparison'
end
else
begin
print 'do string comparison'
end

Short guid in SQL Server / converting from a character string to uniqueidentifier

I need to create a column witch will contain short guid. So I found out something like this:
alter table [dbo].[Table]
add InC UNIQUEIDENTIFIER not null default LEFT(NEWID(),6)
But I get the error:
Conversion failed when converting from a character string to uniqueidentifier.
I've been trying
LEFT(CONVERT(varchar(36),NEWID()),6)
and
CONVERT(UNIQUEIDENTIFIER,LEFT(CONVERT(varchar(36),NEWID()),6))
But I am still getting the same error.
There is no such thing as "short guid". Guid, or uniqueidentifier is a 16 byte data type. You can read about it in MSDN. It means that the length must always be 16 bytes and you cannot use 6 characters as you are trying to do.
In the same MSDN article you can find description how you can initialize this type:
A column or local variable of uniqueidentifier data type can be
initialized to a value in the following ways:
By using the NEWID function.
By converting from a string constant in the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, in which each x is a
hexadecimal digit in the range 0-9 or a-f. For example,
6F9619FF-8B86-D011-B42D-00C04FC964FF is a valid uniqueidentifier
value.
In your case you are trying to convert only 6 characters to uniqueidentifier which obviously fails.
If you want to use just 6 characters, just use varchar(6):
alter table [dbo].[Table]
add InC varchar(6) not null default LEFT(NEWID(),6)
Keep in mind that in this case this guid is not guaranteed to be unique.
Using CRYPT_GEN_RANDOM instead of NEWID can improve random distribution of the string.
SELECT LEFT(CAST(CAST(CRYPT_GEN_RANDOM(16) AS UNIQUEIDENTIFIER) AS VARCHAR(50)), 6)
I just made this one since I couldn't find a good answer on the internet.
Please keep in mind this is a 64 bit representation of a 128bit value, so it has twice the collision possibilities that a real GUID would have. Does not handle 0.
Function takes a NEWID value: 6A10A273-4561-40D8-8D36-4D3B37E4A19C
and shortens it to : 7341xIlZseT
DECLARE #myid uniqueidentifier= NEWID()
select #myid
DECLARE #bigintdata BIGINT = cast(cast(reverse(NEWID()) as varbinary(max)) as bigint)
DECLARE #charSet VARCHAR(70) = '1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
DECLARE #cBase int = LEN(#charSet)
DECLARE #sUID varchar(22) = ''
DECLARE #x int
WHILE (#bigintdata <> 0)
BEGIN
SET #x = CAST(#bigintdata % #cBase as INT) + 1
SET #bigintdata = #bigintdata / #cBase
SET #sUID = SUBSTRING(#charSet, #x, 1) + #sUID;
END
SELECT #sUID

SQL Server - Cast invalid value to int

Is there any way to deal with SQL casts if the input data is corrupt?
Let's say I have a column of datatype NVarchar(10) and want to cast this column to int.
Let's also say that some of the nvarchar values are corrupt, so they can't be converted to int.
Is there any way to silently ignore these, default them to 0 or some such?
DECLARE #t TABLE (Numbers VARCHAR(20))
INSERT INTO #t
VALUES
('30a'),('30'),('100'),
('100a'),('200'),('200a')
SELECT CASE
WHEN ISNUMERIC(Numbers) = 1
THEN CAST(Numbers AS INT) ELSE NULL END AS Number
FROM #t
ISNUMERIC Function returns 1 when it is an integer value you can use this function.
Result
Number
NULL
30
100
NULL
200
NULL
it will cast the integer values to INT and ignore the values that cannot be cast to Int
Try this with PatIndex() function:
select id, val
from t
where patindex('%[^0-9]%',val) = 0
Note: above query is filtering out corrupted values, if you need to bring them in with 0 values, please use a case expression as below.
select id, case when patindex('%[^0-9]%',val) = 0
then convert(int, val)
else 0 end val
from t
Fiddle demo for both queries
I'll be the unpopular one and advise REGEX because ISNUMERIC, while sometimes useful, doesn't catch everything. This answer on SO excellently covers some REGEX concepts, for instance:
One numeric digit
Probably the easiest one of the bunch:
WHERE Column LIKE '[0-9]'
For more details, here's a useful REGEX workbench by Phil Factor and Robyn Pae.

Convert number stored as text data type to int

I have a database that is a result of an import. The database is a deliverable, I did not do the import myself, nor do I have access to the original data to do it myself. That being said, there is an integer value that was imported to a text datatype. All of the stored values are valid integers. I keep getting:
Explicit conversion from data type text to int is not allowed.
if I try to change the field data type in the table. I have also created a new INT field in the table and tried to update it based upon the value in the TEXT field, but I receive the same error. Lastly I tried to create a new table and tried to insert the old values but cannot convert or cast to the int successfully.
This seems to work: CONVERT(INT, CONVERT(VARCHAR(MAX),myText))
Edit:
I'm not totally sure of what's the best choice for the inner conversion... Choosing either VARCHAR(N) with N > 10 or VARCHAR(MAX) has the advantage of not preventing an overflow by truncating (assuming the overflow is the preferred behavior in that case).
Also, the conversion to INT seems to treat leading spaces as zero. So VARCHAR(MAX) reduces the chance of erroneously getting zero. E.g.:
CREATE TABLE #foo ( bar TEXT )
INSERT INTO #foo
VALUES (' 10')
SELECT CONVERT (INT, CONVERT(VARCHAR(MAX),bar)) FROM #foo -- 10
SELECT CONVERT (INT, CONVERT(VARCHAR(10),bar)) FROM #foo -- 0
Probably the best thing is to do some validation to make sure the input meets whatever your requirements are.
TextValue to Int direct Conversion is not possible, so
convert TextValue to varchar(max)
varchar(max) to int or bigint
Example :
convert(int, (convert( varchar(max),'TextValue'))) as ColumnName
You need to convert text type to varchar(x), after that you can cast or convert to int. To avoid double convert i prefer cast.
CAST(CONVERT(VARCHAR(50),CONFIG_VALUE) AS INT)
Full example:
DECLARE #age int;
SET #age = (SELECT CAST(CONVERT(varchar(50),#yourTextVarHere) AS INT))
SELECT #age

Converting varchar to int, SQL Server

I have code like this:
CREATE FUNCTION gantistok (#id VARCHAR(8),
#id_t INT)
RETURNS INT
BEGIN
DECLARE #tahu INT,
#tempe INT,
#hasil INT;
SELECT #tahu = CONVERT(INT, stok)
FROM barang
WHERE id_barang = #id;
SELECT #tempe = CONVERT(INT, jumlah)
FROM det_trans
WHERE id_det_trans = #id_t;
SET #hasil = #tahu - #tempe;
RETURN #hasil
END
Why doesn't it work? I am getting this error:
Msg 402, Level 16, State 1, Procedure gantistok, Line 5
The data types text and varchar are incompatible in the equal to operator.
you are using wrong syntax
it should be
CONVERT(expr,type)
and type must be SIGNED [INTEGER]
REFERENCE
MySQL? SQL Server? which one?
What is type of id_barang stok for table barang?
Guessing the problem expression is id_barang=#id
The SQL Server convert() function does not allow convert TEXT to int(INT4).
problem is on id_barang = #id.
id_barang contains a value that RDBMS is not able to convert to integer.
id_barang is a varchar.
So if you can't convert id_barang to integer, then you have to convert #id to varchar in the query:
SELECT #tahu = CONVERT(INT, stok)
FROM barang
WHERE id_barang = CONVERT(varchar(50), #id);
I'm using varchar(50) because I don't know what kind of varchar exactly id_barang is.
I would suggest to always do it this way.
Even if id_barang would not contain non-integer values at the moment...it's still a text column!
Someone could insert a non-integer value anytime, so I would always make sure that my queries will work in this case as well.

Resources