Getting at string data in SQL - sql-server

I have a row entry with the following format:
Site=[number];this=that;foo=bar;
[number] above can be from 1...infinity. So I need to split out the [number] to use in another select statements where clause. Site=[number] is always at the beginning in the string and the data is always separated by a semi-colon.

declare #t nvarchar(100) = 'Site=230;this=that;foo=bar;';
select convert(int, substring(#t,6, charindex(';',#t,0)-6))

SELECT SUBSTRING(col, 1, CHARINDEX(col,';'))

Why are you storing data in the database in this format? Split it up into columns so that you can do meaningful queries.

You can play with the string this way:
declare #tx as nvarchar(100)
set #tx = 'Site=[number];this=that;foo=bar;'
print substring(
#tx,
CHARINDEX('[', #tx)+1,
CHARINDEX(']',#tx)-CHARINDEX('[',#tx)-1)
Hope this helps.

I don't have MS Sql Server available to try this out, but have you tried something like
Select
field
convert(bigint, substring(field, 6)) as thenum
from
thetable
where
condition=something
where field is the name of the field containing site=[number];...
The theory goes that substring will strip off site= off the beginning, and convert
will (hopefully) convert the number portion and ignore the rest of the text from the semicolon onwards.
It may or may not work. If not you may need to write an elaborate function instead.

Related

SQL SUBSTRING & PATINDEX of varying lengths

SQL Server 2017.
Given the following 3 records with field of type nvarchar(250) called fileString:
_318_CA_DCA_2020_12_11-01_00_01_VM6.log
_319_CA_DCA_2020_12_12-01_VM17.log
_333_KF_DCA01_00_01_VM232.log
I would want to return:
VM6
VM17
VM232
Attempted thus far with:
SELECT
SUBSTRING(fileString, PATINDEX('%VM[0-9]%', fileString), 3)
FROM dbo.Table
But of course that only returns VM and 1 number.
How would I define the parameter for number of characters when it varies?
EDIT: to pre-emptively answer a question that may come up, yes, the VM pattern will always be proceeded immediately by .log and nothing else. But even if I took that approach and worked backwards, I still don't understand how to define the number of characters to take when the number varies.
here is one way :
DECLARE #test TABLE( fileString varchar(500))
INSERT INTO #test VALUES
('_318_CA_DCA_2020_12_11-01_00_01_VM6.log')
,('_319_CA_DCA_2020_12_12-01_00_01_VM17.log')
,('_333_KF_DCA_2020_12_15-01_00_01_VM232.log')
-- 5 is the length of file extension + 1 which is always the same size '.log'
SELECT
REVERSE(SUBSTRING(REVERSE(fileString),5,CHARINDEX('_',REVERSE(fileString))-5))
FROM #test AS t
This will dynamically grab the length and location of the last _ and remove the .log.
It is not the most efficient, if you are able to write a CLR function usnig C# and import it into SQL, that will be much more efficient. Or you can use this as starting point and tweak it as needed.
You can remove the variable and replace it with your table like below
DECLARE #TESTVariable as varchar(500)
Set #TESTVariable = '_318_CA_DCA_2020_12_11-01_00_01_VM6adf.log'
SELECT REPLACE(SUBSTRING(#TESTVariable, PATINDEX('%VM[0-9]%', #TESTVariable), PATINDEX('%[_]%', REVERSE(#TESTVariable))), '.log', '')
select *,
part = REPLACE(SUBSTRING(filestring, PATINDEX('%VM[0-9]%', filestring), PATINDEX('%[_]%', REVERSE(filestring))), '.log', '')
from table
Your lengths are consistent at the beginning. So get away from patindex and use substring to crop out the beginning. Then just replace the '.log' with an empty string at the end.
select *,
part = replace(substring(filestring,33,255),'.log','')
from table;
Edit:
Okay, from your edit you show differing prefix portions. Then patindex is in fact correct. Here's my solution, which is not better or worse than the other answers but differs with respect to the fact that it avoids reverse and delegates the patindex computation to a cross apply section. You may find it a bit more readable.
select filestring,
part = replace(substring(filestring, ap.vmIx, 255),'.log','')
from table
cross apply (select
vmIx = patindex('%_vm%', filestring) + 1
) ap

Build a SQL query with a DateTime parameter

I can successfully use a Query with a Date parameter in string format as
SELECT * FROM ORDERS WHERE [DATE]='20160209'
but I haven't seen any sample of a Query specifying a DateTime parameter in string format.
Next samples are rejected by Microsoft SQL Server Management Studio:
SELECT * FROM ORDERS WHERE [DATE]='20130523T153500000Z'
SELECT * FROM ORDERS WHERE [DATE]='2013-05-23T15:35:00:000Z'
I know this is not a good practice and I should pass DateTime values rather than strings, but sometimes it is useful for debugging.
What is the right format to include a string formatted datetime on a SQL query?
No so sure where you've got those date formats...
This one '2013-05-23T15:35:00:000Z' just doesn't seem to be right. I haven't seen that nanoseconds were delimited by a ':' character. It is usually a decimal of a second, so '2013-05-23T15:35:00.000Z' is a better format and it works:
select convert(DateTime,'2013-05-23T15:35:00.000Z')
As for the other, you might need to do the parsing yourself:
select CONVERT(DATETIME,LEFT('20130523T153500000Z',4)+SUBSTRING('20130523T153500000Z',5,2)+SUBSTRING('20130523T153500000Z',7,2))
hope this helps.
Can you just do something like this?
SELECT *
FROM ORDERS
WHERE [DATE] = CONVERT(DATETIME,'20130523T153500000Z')
As long as the string is in a workable format.
If it's just for debugging, you might do something like:
DECLARE #val VARCHAR(25)
-- Easily swapped out with different testing values
SET #val = '20130523T153500000Z'
SELECT *
FROM Orders
WHERE [DATE] = CAST(#val AS DATETIME)
-- You could also use CONVERT

Get only numeric part of a column data?

I have a column in my database containing both numeric and alphanumeric characters.
I only want to get the numeric (6 numbers) from the column.
Example of data:
TEST_123456_Prod
DB111111P
F222222FN
PROD999999_SCF
I want to create a select statement that returns all rows from this column where all but numbers are filtered out.
I´m using SQL Server, so probably Charindex needs to be used, but no idea how.
To strip off all alphanumeric characters you can create a function as:
CREATE FUNCTION [dbo].[RemoveAlphaCharacters](#InputString VARCHAR(1000))
RETURNS VARCHAR(1000)
AS
BEGIN
WHILE PATINDEX('%[^0-9]%',#InputString)>0
SET #InputString = STUFF(#InputString,PATINDEX('%[^0-9]%',#InputString),1,'')
RETURN #InputString
END
GO
and then use it to get desired result as:
select dbo.RemoveAlphaCharacters(databasename)
from T1;
SQL Fiddle
This will work for all of your examples:
SELECT
SUBSTRING(databasename,
PATINDEX('%[0-9]%', databasename),
LEN(databasename) - (PATINDEX('%[0-9]%', REVERSE(databasename)) + PATINDEX('%[0-9]%', databasename)) + 2)
FROM dbs
Here is a SQLFiddle with how the code works.

converting a varchar to datetime in sql server

I have a varchar 20130909132512 and I would like to convert it into just a date 2013-09-09
I keep getting an error when trying
select convert(datetime,'20130909132512',105)
and I am trying to avoid using
select convert(datetime,SUBSTRING('20130909132512',0,8),105)
if possible. Any ideas on how I can do this?
You could transform your varchar to 20130909 13:25:12 using STUFF
Declare #a Varchar(20)
Select #a = '20130909132512'
select convert(datetime,
STUFF(STUFF(STUFF(#a,13,0,':'),11,0,':'),9,0,' ')
,105)
Whether you use bummi's STUFF method or continue using SUBSTRING, you're going to have to pre-format the string no matter what you do.
In this case, SUBSTRING will perform a bit faster
SELECT CONVERT(date, SUBSTRING('20130909132512', 0, 9), 20)
You'll want to use "20" as the conversion style, though, if you want the date in the format 2013-09-09.

Using HashBytes in SQL Server returns different results from DB

I try to calculate md5 hash on a certain value, but I get a weird result.
I run it in two different ways:
SELECT HASHBYTES('md5',ZLA_PASSWORD),ZLA_PASSWORD, len(ZLA_PASSWORD) FROM ZLA_PASSWORD;
SELECT HASHBYTES('md5', '123456');
I get two different results, where only the second one is valid:
0xCE0BFD15059B68D67688884D7A3D3E8C 123456 6
0xE10ADC3949BA59ABBE56E057F20F883E
This is done on an SQL Server 2005.
checking the result of MD5 on 123456 was the same as the second result checking online.
Any ideas?
Thanks!
You have different data types
declare #str1 as varchar(10)
declare #str2 as nvarchar(10)
set #str1 = '123456'
set #str2 = '123456'
select
hashbytes('md5', #str1) as 'varchar',
hashbytes('md5', #str2) as 'nvarchar'
Result
varchar nvarchar
0xE10ADC3949BA59ABBE56E057F20F883E 0xCE0BFD15059B68D67688884D7A3D3E8C
LEN Trims the contents before returning the length (of the trimmed string.)
Most likely your password field is a CHAR field and got whitespace in there.
Try doing a RTRIM before hashing:
SELECT HASHBYTES('md5',RTRIM(ZLA_PASSWORD))
More exactly this should solve the issue:
SELECT HASHBYTES('md5',CAST(ZLA_PASSWORD AS varchar)),ZLA_PASSWORD, len(ZLA_PASSWORD) FROM ZLA_PASSWORD;

Resources