Error converting varchar to bigint (CONVERT, SUBSTRING, PATINDEX) - sql-server

In the following sproc I'm having troubles converting my id into a bigint when returning. The id is of the form {letters}{numbers}, where {letters} can be 2 or 3 characters long and {numbers} can be any length. I'm trying to first grab the numbers from my id and then convert these to bigint and return this in place of the id field. My understanding for SUBSTRING is that I can use PATINDEX to get the first index where a number is encountered and grab the substring from that index. I set length to 50 only because I don't know how long a person's actual id is and 50 is the max length for [id] to begin with.
ALTER PROCEDURE [dbo].[GetSummoner]
#Id varchar(50)
AS
BEGIN
SET NOCOUNT ON;
SELECT
CONVERT(bigint, SUBSTRING([id], (PATINDEX('%[^0-9]%', [id])), 50)) AS id
,[name]
,[modify_date]
,[profile_icon_id]
,[revision_date]
,[summoner_level]
FROM [Summoners]
WHERE [id]=#Id
END
Edit: Error message: "Error converting data type varchar to bigint."

You are using the wrong PATINDEX. remove the ^ char.
Also, whenever you encounter problems like this the easy way to debug it is running the select without the convert and see what you get.
CONVERT(bigint, SUBSTRING([id], (PATINDEX('%[0-9]%', [id])), 50)) As id

Related

SQL computed column - formula to calculate length and do a substring

Hi I'm looking for a easier solution to one of the columns in SQL table. The column has a datatype of nvarchar(50). However, I want to put a formula in the computed column field of this column whereby:
check if the length of the data being inserted is more than 50.
If it is, then take the first 36 characters.
create the string - "[SQL-Truncated]…"+"the 34 characters from previous step" ([SQL-Truncated]... is 16 characters in length.)
insert this new string in that column instead, thereby ensuring we only get 50 chars.
You can try something like this: create a stored function
CREATE FUNCTION dbo.TrimLongerThan50(#Input NVARCHAR(500))
RETURNS NVARCHAR(50)
AS BEGIN
DECLARE #Result NVARCHAR(50)
SET #Result = #Input
IF LEN(#Input) > 50
SET #Result = N'[SQL-Truncated] ' + SUBSTRING(#input, 1, 34)
RETURN #result
END
and then use it in the computed column
ALTER TABLE dbo.YourTable
ADD NewComputedColumn AS dbo.TrimLongerThan50(YourInputColumn)
the formula isn't that complicated but i'm not quite sure if you really want to create a computed column.
alter table add mytruncatedtext
as ( case when len(origcolumn) > 50
then N'[SQL-Truncated] ' + left(origcolumn, 34)
else origcolumn
end )
persisted

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 : converting varchar to INT

I am stuck on converting a varchar column UserID to INT. I know, please don't ask why this UserID column was not created as INT initially, long story.
So I tried this, but it doesn't work. and give me an error:
select CAST(userID AS int) from audit
Error:
Conversion failed when converting the varchar value
'1581............................................................................................................................' to data type int.
I did select len(userID) from audit and it returns 128 characters, which are not spaces.
I tried to detect ASCII characters for those trailing after the ID number and ASCII value = 0.
I have also tried LTRIM, RTRIM, and replace char(0) with '', but does not work.
The only way it works when I tell the fixed number of character like this below, but UserID is not always 4 characters.
select CAST(LEFT(userID, 4) AS int) from audit
You could try updating the table to get rid of these characters:
UPDATE dbo.[audit]
SET UserID = REPLACE(UserID, CHAR(0), '')
WHERE CHARINDEX(CHAR(0), UserID) > 0;
But then you'll also need to fix whatever is putting this bad data into the table in the first place. In the meantime perhaps try:
SELECT CONVERT(INT, REPLACE(UserID, CHAR(0), ''))
FROM dbo.[audit];
But that is not a long term solution. Fix the data (and the data type while you're at it). If you can't fix the data type immediately, then you can quickly find the culprit by adding a check constraint:
ALTER TABLE dbo.[audit]
ADD CONSTRAINT do_not_allow_stupid_data
CHECK (CHARINDEX(CHAR(0), UserID) = 0);
EDIT
Ok, so that is definitely a 4-digit integer followed by six instances of CHAR(0). And the workaround I posted definitely works for me:
DECLARE #foo TABLE(UserID VARCHAR(32));
INSERT #foo SELECT 0x31353831000000000000;
-- this succeeds:
SELECT CONVERT(INT, REPLACE(UserID, CHAR(0), '')) FROM #foo;
-- this fails:
SELECT CONVERT(INT, UserID) FROM #foo;
Please confirm that this code on its own (well, the first SELECT, anyway) works for you. If it does then the error you are getting is from a different non-numeric character in a different row (and if it doesn't then perhaps you have a build where a particular bug hasn't been fixed). To try and narrow it down you can take random values from the following query and then loop through the characters:
SELECT UserID, CONVERT(VARBINARY(32), UserID)
FROM dbo.[audit]
WHERE UserID LIKE '%[^0-9]%';
So take a random row, and then paste the output into a query like this:
DECLARE #x VARCHAR(32), #i INT;
SET #x = CONVERT(VARCHAR(32), 0x...); -- paste the value here
SET #i = 1;
WHILE #i <= LEN(#x)
BEGIN
PRINT RTRIM(#i) + ' = ' + RTRIM(ASCII(SUBSTRING(#x, #i, 1)))
SET #i = #i + 1;
END
This may take some trial and error before you encounter a row that fails for some other reason than CHAR(0) - since you can't really filter out the rows that contain CHAR(0) because they could contain CHAR(0) and CHAR(something else). For all we know you have values in the table like:
SELECT '15' + CHAR(9) + '23' + CHAR(0);
...which also can't be converted to an integer, whether you've replaced CHAR(0) or not.
I know you don't want to hear it, but I am really glad this is painful for people, because now they have more war stories to push back when people make very poor decisions about data types.
This question has got 91,000 views so perhaps many people are looking for a more generic solution to the issue in the title "error converting varchar to INT"
If you are on SQL Server 2012+ one way of handling this invalid data is to use TRY_CAST
SELECT TRY_CAST (userID AS INT)
FROM audit
On previous versions you could use
SELECT CASE
WHEN ISNUMERIC(RTRIM(userID) + '.0e0') = 1
AND LEN(userID) <= 11
THEN CAST(userID AS INT)
END
FROM audit
Both return NULL if the value cannot be cast.
In the specific case that you have in your question with known bad values I would use the following however.
CAST(REPLACE(userID COLLATE Latin1_General_Bin, CHAR(0),'') AS INT)
Trying to replace the null character is often problematic except if using a binary collation.
This is more for someone Searching for a result, than the original post-er. This worked for me...
declare #value varchar(max) = 'sad';
select sum(cast(iif(isnumeric(#value) = 1, #value, 0) as bigint));
returns 0
declare #value varchar(max) = '3';
select sum(cast(iif(isnumeric(#value) = 1, #value, 0) as bigint));
returns 3
I would try triming the number to see what you get:
select len(rtrim(ltrim(userid))) from audit
if that return the correct value then just do:
select convert(int, rtrim(ltrim(userid))) from audit
if that doesn't return the correct value then I would do a replace to remove the empty space:
select convert(int, replace(userid, char(0), '')) from audit
This is how I solved the problem in my case:
First of all I made sure the column I need to convert to integer doesn't contain any spaces:
update data set col1 = TRIM(col1)
I also checked whether the column only contains numeric digits.
You can check it by:
select * from data where col1 like '%[^0-9]%' order by col1
If any nonnumeric values are present, you can save them to another table and remove them from the table you are working on.
select * into nonnumeric_data from data where col1 like '%[^0-9]%'
delete from data where col1 like '%[^0-9]%'
Problems with my data were the cases above. So after fixing them, I created a bigint variable and set the values of the varchar column to the integer column I created.
alter table data add int_col1 bigint
update data set int_col1 = CAST(col1 AS VARCHAR)
This worked for me, hope you find it useful as well.

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

How rigid is the max size of a VARCHAR in SQL Server?

i.e. if I create a VARCHAR(50) field, what happens if I try to assign it a value that's 100 characters long?
Will SQL Server let me do this? Is it somehow less efficient?
If you try forcing a large string into a smaller-size variable, the incoming string will be simply chopped off at the appropriate size.
declare #Variable varchar (50)
set #Variable = replace (SPACE (100), ' ' , '.')
print #Variable
the output is 50 characters long
..................................................
If you try to force a large string into a small sized Field in a Table, an Error will be raised
declare #MyTable Table
(
TestVariable varchar (50)
)
insert into #MyTable (TestVariable) select replace (SPACE (100), ' ' , '.')
select * from #MyTable
the output is
Msg 8152, Level 16, State 14, Line 6
String or binary data would be truncated.
The statement has been terminated.
TestVariable
------------------------------------------------
It will throw an error saying that the value would be truncated. It won't write more than the 50 characters you've specified, otherwise you wouldn't be able to prevent the row size from growing out of control
Will SQL Server let me do this? Is it somehow less efficient?
It will emit an error, saying that the string or binary data would be truncated.

Resources