Access query vs SQL Server 2008 query - sql

I'm trying to convert this query from an Access db to work in SQL Server 2008 and got stuck. I know there are differences, but I'm not sure what's going on and apparently I'm not very good at this.
Any help would be appreciated.
Access
Mid(Trim([SC01039]),
InStrRev(Trim([SC01039])," ")+3,4)
AS ProductType
SQL Server 2008 (This is what I tried changing it to)
Substring(RTrim(LTrim([SC01039])),
Right(RTrim(LTrim([SC01039])),
CHARINDEX(' ',RTrim(LTrim([SC01039]))))+3,4)
AS ProductType
The error I receive is
"Conversion failed when converting the nvarchar value 'L318' to data
type int."
Why is it trying to convert the resulting text into an integer? My assumption is the query is saying, "Find the position of the space closest to the right of the string, now add 3 to that position and give me the next 4 characters." It seems to be a problem with the data, not the query (what does it do if there is no space? Or the string is null?) I dunno...
Did I even get close? :P
There are mixed characters in SC01039, but this is a sample:
SC01039 : Expected Output
------------- : ---------------
QC 06999911 : 9999
SW 12FMT116 : FMT1
26RMF399 : RMF3
08 : [empty]
[empty] : [empty]
Apparently it is always 4 characters, starting 3 to the right of the first space found (searching for the space from right-to-left). Some data in SC01039 have multiple spaces (ie: 09 TVR 012 2, in this case it doesn't return anything and I believe that is OK).

You problem is with Right(RTrim(LTrim([SC01039])), part of your code. Why do you need it? Because what I've shown below should do the trick.
Try this:
Substring(RTrim(LTrim([SC01039])),
CHARINDEX(' ',RTrim(LTrim([SC01039])))+3,4)
AS ProductType
The Substring is expecting SUBSTRING(expression, start, length) and you provided the second parameter with a nvarchar;
Right(RTrim(LTrim([SC01039])),
CHARINDEX(' ',RTrim(LTrim([SC01039]))))+3
hence your error.
Create this function (you don't have to put it helps with readability
CREATE FUNCTION InStrRev(#Val nvarchar(max), #substr nvarchar(max))
RETURNS int
AS
BEGIN
RETURN CASE WHEN CHARINDEX(#substr, RTrim(LTrim(Reverse(#Val)))) = 0 THEN 0 ELSE LEN(#Val) - CHARINDEX(#substr, RTrim(LTrim(Reverse(#Val)))) + 1 END -- add one because you want a start position
END
and use it in your code like this
Substring(RTrim(LTrim([SC01039])), dbo.InStrRev([SC01039], ' ') + 3, 4) AS ProductType
Hope it helps

Related

SQL CASE statement needs to handle Text

Apologies if this has been asked before - I've spent a couple of hours searching but not found anything that's helped.
It's quite simple really - I've been asked to create a query which includes a field that when it was set up (not by me) was created as a VARCHAR instead of an INT.
I need to do some calculations on this field, however some users have been entering text into it, so the calculations fail as it can't convert the data to an INT.
Is there anything I can add to a CASE statement to handle where there's text?
I was thinking something like the below, but don't know what the actual code is:
CASE
WHEN [Field1] IS TEXT THEN 1 ;
ELSE [Field2] as [Chose name]
END
Edit: Note that this is in MS SQL Server.
Thanks.
In SQL Server, you can use try_convert() and isnull() for this:
isnull(try_convert(int, field), 1)
try_convert() attempts you cast field to an int. When that fails, null is returned; you can trap that with isnull() and turn the result to 1 instead.
Note that this only works as long as field is not null (otherwise, you would get 1 as a result).
In SQL Server
Declare #Salary varchar(100);
Set #Salary = 50000;
Select Case when ISNUMERIC(#Salary) = 1 then 1
else 0 end as [Check]
May be this will be Helpful.

Matching on Values, but Erroring on New Value in SQL Server

I am comparing data from two different databases (one MariaDB and one SQL Server) within my Node project, and am then doing inserts and updates as necessary depending on the comparison results.
I have a question about this code that I use to iterate through results in Node, going one at a time and passing in values to check against (note - I am more familiar with Node and JS than with SQL, hence this question):
SELECT TOP 1
CASE
WHEN RM00101.CUSTCLAS LIKE ('%CUSR%')
THEN CAST(REPLACE(LEFT(LR301.DOCNUMBR, CHARINDEX('-', LR301.DOCNUMBR)), '-', '') AS INT)
ELSE 0
END AS Id,
CASE
WHEN LR301.RMDTYPAL = 7 THEN LR301.ORTRXAMT * -1
WHEN LR301.RMDTYPAL = 9 THEN LR301.ORTRXAMT * -1
ELSE LR301.ORTRXAMT
END DocumentAmount,
GETDATE() VerifyDate
FROM
CRDB..RM20101
INNER JOIN
CRDB..RM00101 ON LR301.CUSTNMBR = RM00101.CUSTNMBR
WHERE
CONVERT(BIGINT, (REPLACE(LEFT(LR301.DOCNUMBR, CHARINDEX('-', LR301.DOCNUMBR)), '-', ''))) = 589091
Currently, the above works for me for finding records that match. However, if I enter a value that doesn't yet exist - in this line below, like so:
WHERE CONVERT(BIGINT, (REPLACE(LEFT( LR301.DOCNUMBR, CHARINDEX('-', LR301.DOCNUMBR)), '-', ''))) = 789091
I get this error:
Error converting data type varchar to bigint.
I assume the issue is that, if the value isn't found, it can't cast it to an INTEGER, and so it errors out. Sound right?
What I ideally want is for the query to execute successfully, but just return 0 results when a match is not found. In JavaScript I might doing something like an OR clause to handle this:
const array = returnResults || [];
But I'm not sure how to handle this with SQL.
By the way, the value in SQL Server that's being matched is of type char(21), and the values look like this: 00000516542-000. The value in MariaDB is of type INT.
So two questions:
Will this error out when I enter a value that doesn't currently match?
If so, how can I handle this so as to just return 0 rows when a match isn't found?
By the way, as an added note, someone suggested using TRY_CONVERT, but while this works in SQL Server, it doesn't work when I use it with the NODE mssql package.
I think the issue is happening because the varchar value is not always made of numbers. You can make the comparison in varchar format itself to avoid this issue:
WHERE (REPLACE(LEFT( LR301.DOCNUMBR, CHARINDEX('-', LR301.DOCNUMBR)), '-', '')) = '789091'
Hope this helps.
Edit: based on the format in the comment, this should do the trick;
WHERE REPLACE(LTRIM(REPLACE(REPLACE(LEFT( LR301.DOCNUMBR, CHARINDEX('-', LR301.DOCNUMBR)),'0',' '),'-','')),' ','0') = '789091'

DB2 SQL Anything left of a /

I've been working on this for days and can't seem to work it out. Basically I need return digits from a field before there is a forward slash. e.g. if the field was 1234/TEXT I want to return 1234. I can't just use left fieldname 4 as the digits vary in left e.g. 12345/TEXT, so it needs to be anything left of the forward slash. Now in the World of MS Access, it is something like this - and it works
Left(TABLE!FIELD,InStr(1,TABLE!FIELD,"/")-1)
However, how do I convert this to be used in an IBM\DB2 system? The DB2 SQL seems somewhat different to 'normal' SQL.
Thanks!
Rather than INSTR, maybe LOCATE
LOCATE(char, string)
char is the search term
string is the string being searched
You can achieve this by combining LOCATE with SUBSTR;
Locate information
Substring information
Cheat sheet (for this example);
SUBSTRING('FIELD','START POSITION', 'LENGTH')
LOCATE('SEARCH STRING', 'SOURCE STRING')
SUBSTRING lets you retrieve specific characters from a string, i.e.;
AFIELD = 'Hello'
SUBSTRING(AFIELD,4,2)
Result = 'lo' (position 4 and 5 of Hello)
LOCATE returns the position of the first character of the search string it finds as a number, i.e.;
AFIELD = 'Hello'
LOCATE('ello', AFIELD)
Result = 2 (it starts at position 2)
So you can combine these to do what you want, example;
XTABLE has 1 column called ACOL with the following values in it;
123467/ABCD
1321/ABDD
1123467/ABCD
To just retrieve the numbers;
SELECT SUBSTRING(ACOL,1, LOCATE('/',ACOL)-1)
FROM XRDK/XTABLE
Result;
123467
1321
1123467
What are we doing?
SUBSTRING(
ACOL,
1,
LOCATE('/',ACOL)-1
)
SUBSTRING(
Field ACOL,
Starting at position 1,
Length; using locate set this to where I find a '/' and subtract 1 from the
resulting postion (without the -1 you'd have the / on the end)
)
Try this
SELECT SUBSTRING(CAST (ROUND(COLUMN,2) AS DECIMAL(6,2)), 0, locate('/',CAST (ROUND(COLUMN,2) AS DECIMAL(6,2))))
FROM TABLE

Search half the refID in SQL

I have a SQL table which hold unique REFID (int) and many other columns. I wanted to search a row using the half REFID . So if someone just search 0001 then 50001, 00015... comes up.
I have tried:
SELECT TOP 10 REFID
FROM Tablename
where REFID LIKE '%' + cast(0001 as varchar(10)) +'%'
however the problem is, it also giving me 150100 however I wanted 0001 to be in order.
'0001' is passed in as a parameter passed in from my C# application. I know I can convert the '0001' to string/varchar before sending it to the SQL however I was looking for a way to do it within the SQL so I can pass in the int from C# application
Code:
SELECT TOP 10 REFID
FROM Tablename
where REFID LIKE '%0001%'
0001 is a number and when converted to varchar() it will become '1'.
This will work with any number but only if you know beforehand that you will use four characters in your expression.
SELECT TOP 10 REFID
FROM Tablename
where REFID LIKE '%' + RIGHT('0000' + CAST(0001 AS VARCHAR(4)), 4) +'%'
We don't know how are you building your SQL statement, so we may need more information in order to help. Where do you get your ' 0001' value from? Is it a variable? Is it a parameter in a stored procedure? Is it inside a function in a different programming language?
You need to compare the REFID to a string value (not an int: as the comments point out, CAST(0001 AS VARCHAR(10)) returns 1, not 0001.
SELECT TOP 10 REFID
FROM Tablename
where REFID LIKE '%0001%'
EDIT: you have bigger issues too, like how to search for an integer value stored without leading zeroes, but if you are passing in a parameter you need to either make it varchar, or convert it to varchar in your query body, like so (assuming, of course, that you are always searching for a four-digit string):
SET #SearchParam_char = RIGHT('000' + CAST(#searchParam_Int AS VARCHAR(10)), 4)
I have found:
cast('0001' as varchar(10)) as 0001 === 1 thanks to ALEX K.
SQL will strip leading zero and there is no way of keeping the zero if you don't know the length.
My solution: I will send a string from my application and let SQL search it using the string.

In SQL Server 2008, how do I check if a varchar parameter can be converted to datatype money?

I've got a stored procedure I use to insert data from a csv. The data itself is a mix of types, some test, some dates, and some money fields. I need to guarantee that this data gets saved, even if it's formatted wrong, so, I'm saving them all to varchars. Later, once the data's been validated and checked off on, it will be moved to another table with proper datatypes.
When I do the insert into the first table, I'd like to do a check that sets a flag (bit column) on the row if it needs attention. For instance, if what should be a money number has letters in it, I need to flag that row and add the column name in an extra errormsg field I've got. I can then use that flag to find and highlight for the users in the interface the fields they need to edit.
The date parameters seem to be easy, I can just use IF ISDATE(#mydate) = '0' to test if that parameter could be converted from varchar to datetime. But, I can't seem to find an ISMONEY(), or anything that's remotely equivalent.
Does anyone know what to call to test if the contents of a varchar can legitimately be converted to money?
EDIT:
I haven't tested it yet, but what do you think of a function like this?:
CREATE FUNCTION CheckIsMoney
(
#chkCol varchar(512)
)
RETURNS bit
AS
BEGIN
-- Declare the return variable here
DECLARE #retVal bit
SET #chkCol = REPLACE(#chkCol, '$', '');
SET #chkCol = REPLACE(#chkCol, ',', '');
IF (ISNUMERIC(#chkCOl + 'e0') = '1')
SET #retVal = '1'
ELSE
SET #retVal = '0'
RETURN #retVal
END
GO
Update
Just finished testing the above code, and it works!
money is decimal in effect, so you test this way
Don't use ISNUMERIC out of the box though: it's unreliable. Use this:
ISNUMERIC(MyCOl + 'e0')
Note, if you have 6 decimal places then it will be lost on conversion to money
Other question with more info why: How to determine the field value which can not convert to (decimal, float,int) in SQL Server
Edit:
Can do it in one line if you want
ISNUMERIC(REPLACE(REPLACE(#chkCOl, '$', ''), ',', '') + 'e0')