MS SQL server - convert HEX string to integer - sql-server

This answer to what looks like the same question:
Convert integer to hex and hex to integer
..does not work for me.
I am not able to go to a HEX string to an integer using MS SQL server 2005 CAST or CONVERT. Am I missing something trivial? I have searched extensively, and the best I can find are long-winded user functions to go from a hex string value to something that looks like a decimal int. Surely there is a simple way to do this directly in a query using built in functions rather than writing a user function?
Thanks
Edit to include examples:
select CONVERT(INT, 0x89)
works as expected, but
select CONVERT(INT, '0x' + substring(msg, 66, 2)) from sometable
gets me:
"Conversion failed when converting the varchar value '0x89' to data type int."
an extra explicit CAST:
select CONVERT(INT, CAST('0x89' AS VARBINARY))
executes, but returns 813185081.
Substituting 'Int', 'Decimal', etc for 'Varbinary' results in an error. In general, strings that appear to be numeric are interpreted as numeric if required, but not in this case, and there does not appear to be a CAST that recognizes HEX. I would like to think there is something simple and obvious and I've just missed it.
Microsoft SQL Server Management Studio Express 9.00.3042.00
Microsoft SQL Server 2005 - 9.00.3080.00 (Intel X86) Sep 6 2009 01:43:32 Copyright (c) 1988-2005 Microsoft Corporation Express Edition with Advanced Services on Windows NT 5.1 (Build 2600: Service Pack 3)
To sum up: I want to take a hex string which is a value in a table, and display it as part of a query result as a decimal integer, using only system defined functions, not a UDF.

Thanks for giving some more explicit examples. As far as I can tell from the documentation and Googling, this is not possible in MSSQL 2005 without a UDF or other procedural code. In MSSQL 2008 the CONVERT() function's style parameter now supoprts binary data, so you can do it directly like this:
select convert(int, convert(varbinary, '0x89', 1))
In previous versions, your choices are:
Use a UDF (TSQL or CLR; CLR might actually be easier for this)
Wrap the SELECT in a stored procedure (but you'll probably still have the equivalent of a UDF in it anyway)
Convert it in the application front end
Upgrade to MSSQL 2008
If converting the data is only for display purposes, the application might be the easiest solution: data formatting usually belongs there anyway. If you must do it in a query, then a UDF is easiest but the performance may not be great (I know you said you preferred not to use a UDF but it's not clear why). I'm guessing that upgrading to MSSQL 2008 just for this probably isn't realistic.
Finally, FYI the version number you included is the version of Management Studio, not the version number of your server. To get that, query the server itself with select ##version or select serverproperty('ProductVersion').

Related

SQL Server appears to correctly interpret non-supported string literal formats

Have an instance of SQL Server 2012 that appears to correctly interpret string literal dates whose formats are not listed in the docs (though note these docs are for SQL Server 2017).
Eg. I have a TSV with a column of dates of the format %d-%b-%y (see https://devhints.io/datetime#date-1) which looks like "25-FEB-93". However, this throws type errors when trying to copy the data into the SQL Server table (via mssql-tools bcp binary). Yet, when testing on another table in SQL Server, I can do something like...
select top 10 * from account where BIRTHDATE > '25-FEB-93'
without any errors. All this, even though the given format is not listed in the docs for acceptable date formats and it apparently also can't be used as a castable string literal when writing in new records. Can anyone explain what is going on here?
the given format is not listed in the docs for acceptable date formats
That means it's not supported, and does not have documented behavior. There's lots of strings that under certain regional settings will convert due to quirks in the parsing implementation.
It's a performance-critical code path, and so the string formats are not rigorously validated on conversion. You're expected to ensure that the strings are in a supported format.
So you may need to load the column as a varchar(n) and then convert it. eg
declare #v varchar(200) = '25-FEB-93'
select convert(datetime,replace(#v,'-',' '),6)
Per the docs format 6 is dd mon YY, but note that this conversion "works" without replacing the - with , but that's an example of the behavior you observed.

SQL Server Concatenation of Different Data Types

Is it possible to concatenate different data types in T-SQL that does not require to convert everything to the same data type?
Below code show the scenario:
DECLARE #weight INT = 50
PRINT 'The weight is' + #weight + 'years old'
Depends how you concatenate, if you use + you'll need an explicit conversion, but you can use the concat function and it'll implicitly convert the parameters for you. Having said that doing things explicitly is very often a good idea.
If you are using version < SQL Server 2012 , you have only one option which is to +. In this case, you are left with no other option than explicit conversion.
But, with the versions starting from SQL Server 2012 you can use CONCAT which does implicit conversions for you.

SELECT DAY('2007-04-30T01:01:01.1234567 -07:00') does not work?

This sql statement:
SELECT DAY('2007-04-30T01:01:01.1234567 -07:00');
is copied from the SQL Server 2012 documentation and tested in my SQL Server 2012 express edition environment. But there was an error saying
Conversion failed when converting date and/or time from character string.
I understand that the character type argument passed in DAY() is unable to be converted to a datetime type value, meaning it has the wrong format (incompatible with some current settings related to SET DATEFORMAT or any settings I don't know). So that's what I would like to know about. Could you explain why that sample statement (not of mine) does not work in my environment. My SQL Server instance was installed with default settings, I've not changed anything after installing it.
By modifying the input string a little, it works:
SELECT DAY('2007-04-30T01:01:01.123'); -- Works!
But these don't (saying the same error I posted at first):
SELECT DAY('2007-04-30T01:01:01.1234'); -- just add 4
SELECT DAY('2007-04-30T01:01:01.123 -07:00'); -- just add -07:00
Looks like there is some settings related to this problem, please tell me what it might be and how to fix this issue (I don't want to change the input string as I tried to make it work).
Thanks for your time solving my problem!
UPDATE:
Also done as some suggestions, like this:
SELECT DAY('2007-04-30T01:01:01.1234567-07:00');
SELECT DAY('2007-04-30T01:01:01.123-07:00');
but it still does not work.
Well, I found the problem. In fact the statement itself (as some ones suggested) should work, but that's just one side of the problem. The other side is the compatibility level of the current datatbase. In my case it's just 90 (which is SQL Server 2005), so explicit casting is required. By changing the compatibility level to 110 (SQL Server 2012) or explicitly casting, it works expectedly.

Regex for a serial number in T-SQL

I'm a novice at regexs and am currently trying to come up with a simple regex that searches for a serial number in the following format: 0217103200XX, where "XX" can each be a numeric digit. I'm using SQL Server Management Studio to pass the regex as a parameter in a stored procedure. I'm not sure if the syntax is any different from other programming languages. I have the following regex as a reference:
(?:2328\d\d(?:0[1-9]|[1-4]\d|5[0-3])\d{4})
Any suggestions are appreciated.
UPDATE:
I'm actually using this in a SQL Query and not in a .Net application. The format is as follows:
USE [MyDB]
EXEC MyStoredProcedure #regex = '(?:2328\d\d(?:0[1-9]|[1-4]\d|5[0-3])\d{4})'
Use LIKE: there is no native RegEx in SQL Server
LIKE '0217103200[0-9][0-9]'
As OMG Ponies stated - SQL Server does not natively support regex (need to use SQLCLR for 2005+, or xp_cre).
If I have understood your question, you could use a PATINDEX to find the serial numbers
Select *
From dbo.MyTable
Where PATINDEX('0217103200[0-9][0-9]', SerialNumberColumn) > 0

SQL Server Management Studio - using multiple filters in table list?

In Management Studio, you can right click on the tables group to create a filter for the table list. Has anyone figured out a way to include multiple tables in the filter? For example, I'd like all tables with "br_*" and "tbl_*" to show up.
Anyone know how to do this?
No, you can't do this. When we first got Management Studio I've tried every possible combination of everything you could think of: _, %, *, ", ', &&, &, and, or, |, ||, etc...
You might be able to roll your own addon to SMSS that would allow you to do what you are looking for:
The Black Art of Writing a SQL Server Management Studio 2005 Add-In
Extend Functionality in SQL Server 2005 Management Studio with Add-ins
The first one is specifically for searching and displaying all schema objects with a given name so you might be able to expand upon that for what you are looking for.
I'm using SQL Server Management Studio v17.1 and it has a SQL injection bug in it's filter construction, so you can actually escape default
tbl.name like '%xxx%'
and write your own query (with some limitations). For example to filter tables that are ending with "_arch", "_hist", "_purge" I used following filter value
_arch') and RIGHT(tbl.name, 5) != N'purge' and RIGHT(tbl.name, 4) != N'hist' and not(tbl.name like N'bbb
You can use SQL Server Profiler to see the constructed query and adjust it as needed.
Not sure if this same bug is available in previous SQL Management Studio versions or when it will be fixed, but for now I'm happy with the result.
I've used Toad for SQL Server (freeware version) which has very nice filtering options.
At first it looks like it could use a CONTAINS query (e.g. "br_*" OR "tbl_*"), but it doesn't seem to. It seems to only support a value that is then passed into a LIKE clause (e.g. 'app' becomes '%app%').
The "sql injection" method still works (v17.5), but with a twist:
zzzz' or charindex('pattern1', name) > 0 or charindex('pattern2', name) > 0 or name like 'zzzz
(I used the 'zzzz' to bypass the '%')
It doesn´t work if '_' or '%' is used in the patterns (or anywhere on your code), because it will automatically be replaced by '[_]' or '[%]' before evaluation.
As others have said, you cannot do this in SQL Server Management Studio (up and including 2014).
The following query will give you a filtered list of tables, if this is all you need:
SELECT
CONCAT(TABLE_SCHEMA, '.', TABLE_NAME) AS TABLE_SCHEMA_AND_NAME,
TABLE_SCHEMA,
TABLE_NAME
FROM
INFORMATION_SCHEMA.TABLES
WHERE
TABLE_SCHEMA IN ('X', 'Y', 'Z') -- schemas go here
ORDER BY
TABLE_SCHEMA,
TABLE_NAME;
The SQL injection method still works (somewhat) as of SSMS 2017 v17.8.1, although it puts brackets around the % symbol, so it will interpret those literally.
If you're using the Name->Contains filter, Profiler shows:
... AND dtb.name LIKE N'%MyDatabase1%')
So, in the Name->Contains field: MyDatabase1') OR (dtb.name LIKE 'MyDatabase2 should do it for simple cases.
This is old I know, but it's good to know that it can works if you input just entering the "filter" text. Skip * or % or any other standard search characters, just enter br_ or tbl_ or whatever you want to filter on.
Your in luck, I just conquered that feat, although my success is small because you can filter by schema which would allow you see more than 1 table but you have to type the filter text in each time you want to change it.

Resources