Equivalent to VB AndAlso in SQL? - sql

Is there an equivalent to VB's AndAlso/OrElse and C#'s &&/|| in SQL (SQL Server 2005). I am running a select query similar to the following:
SELECT a,b,c,d
FROM table1
WHERE
(#a IS NULL OR a = #a)
AND (#b IS NULL OR b = #b)
AND (#c IS NULL OR c = #c)
AND (#d IS NULL OR d = #d)
For example, if the "#a" parameter passed in as NULL there is no point in evaluating the 2nd part of the WHERE clause (a = #a). Is there a way to avoid this either by using special syntax or rewriting the query?
Thanks,
James.

The only way to guarantee the order of evaluation is to use CASE
WHERE
CASE
WHEN #a IS NULL THEN 1
WHEN a = #a THEN 1
ELSE 0
END = 1
AND /*repeat*/
In my experience this is usually slower then just letting the DB engine sort it out.
TerrorAustralis's answer is usually the best option for non-nullable columns

Try this:
AND a = ISNULL(#a,a)
This function looks at #a. If it is not null it equates the expression
AND a = #a
If it is null it equates the expression
AND a = a
(Since this is always true, it replaces the #b is null statement)

The query engine will take care of this for you. Your query, as written, is fine. All operators will "short circuit" if they can.

Another way is to do:
IF (#a > 0) IF (#a = 5)
BEGIN
END
Another if after the condition will do an "AndAlso" logic.
I want to emphesise that this is just a short way to write:
IF (#a > 0)
IF (#a = 5)
BEGIN
END

Take this example:
SELECT * FROM Orders
WHERE orderId LIKE '%[0-9]%'
AND dbo.JobIsPending(OrderId) = 1
Orders.OrderId is varchar(25)
dbo.JobIsPending(OrderId) UDF with int parameter
No short circuit is made as the conversion fails in dbo.JobIsPending(OrderId) when
Orders.OrderId NOT LIKE '%[0-9]%'
tested on SQL Server 2008 R2

Related

ISNUMERIC and TRY_PARSE in SQL Server [duplicate]

What is the best way to determine whether or not a field's value is an integer in SQL Server (2000/2005/2008)?
IsNumeric returns true for a variety of formats that would not likely convert to an integer. Examples include '15,000' and '15.1'.
You can use a like statement but that only appears to work well for fields that have a pre-determined number of digits...
select * where zipcode like '[0-9][0-9][0-9][0-9][0-9]'
I could write a user defined function that attempts to convert a varchar parameter to an int within a try/catch block but I'm checking with the community to see if someone has come across any succient methods to achieve this goal - preferably one that can be used within the where clause of a SQL statement without creating other objects.
Late entry that handles negative
ISNUMERIC(zipcode + '.0e0') --integer
ISNUMERIC(zipcode + 'e0') --decimal
For more see this
1 approach is
zipcode NOT LIKE '%[^0-9]%'
Double negatives, got to love 'em!
If SQL Server 2005+, I'd enable CLR and create the function to support regexes. For SQL Server 2000, see this article for creating a UDF to do the same thing.
Then I'd use the regex: ^\d{5}$
This expression gives 1 for an integer value and 0 otherwise
floor((floor(abs(zipcode)))/abs(zipcode))
Why not just use the following? I can't see to find any cases where it fails.
1 = integer
0 = not integer
null = non-numeric
DECLARE #TestValue nvarchar(MAX)
SET #TestValue = '1.04343234e5'
SELECT CASE WHEN ISNUMERIC(#TestValue) = 1
THEN CASE WHEN ROUND(#TestValue,0,1) = #TestValue
THEN 1
ELSE 0
END
ELSE null
END AS Analysis
It looks like this question needs an updated answer.
Limiting the answer to the question title:
where ISNUMERIC(zipcode) = 1
and zipcode - FLOOR(zipcode) = 0
Expounding based on the text of the question...
Currently-supported versions of SQL Server all support/include the TRY-CONVERT function.
declare #a varchar(100)
set #a = '-1.2a'
--set #a = '-1.2'
--set #a = '-1'
--set #a = '-1.0'
--set #a = '-0'
--set #a = '0'
--set #a = '1'
select #a as 'Value'
, ISNUMERIC(#a) as ISNUMERIC
, case when ISNUMERIC(#a) = 1 and #a - FLOOR(#a) = 0 then 1 else 0 end as ISINTEGER
, case when try_convert(int, #a) >= 0 and left(#a, 1) <> '-' then 1 else 0 end as ISWHOLENUMBER
, case when try_convert(int, #a) > 0 then 1 else 0 end as ISCOUNTINGNUMBER
You'll notice that TRY_CONVERT(INT, -1.0) returns NULL. So TRY_CONVERT(INT, #a) IS NOT NULL is not quite right for ISINTEGER.
case when ISNUMERIC(#a) = 1 and #a - FLOOR(#a) = 0 then 1 else 0 end as ISINTEGER
...works because if ISNUMERIC(#a) = 1 is false, FLOOR(#a) is not evaluated. Reversing the order...
case when #a - FLOOR(#a) = 0 and ISNUMERIC(#a) = 1 then 1 else 0 end as ISINTEGER
...generates an error when the value (#a) is not numeric.
So, for the case of zipcode, assuming you want to verify that a 5-digit zip code is a number and it must be 5 digits (so it can't be zero or less) and would never contain a decimal point (so you don't need to know if 12345.000 is an integer):
where try_convert(int, zipcode) > 0
and len(zipcode) = 5
I came up with the perfect answer for this on another StackO question.
It also proves you cannot use ".0e0" like one user suggests here.
It does so without CLR or non-scalar functions.
Please check it out: https://stackoverflow.com/a/10645764/555798
After moving to sql 2008, I was struggling with isnumeric('\8') returning true but throwing an error when casting to an integer. Apparently forward slash is valid currency for yen or won - (reference http://www.louiebao.net/blog/200910/isnumeric/)
My solution was
case when ISNUMERIC(#str) > 0 and not rtrim(#str) LIKE '[^0-9]%' and not rtrim(#str) LIKE '%[^0-9]' and not rtrim(#str) LIKE '[^0-9]%' then rtrim(#str) else null end
See whether the below code will help.
In the below values only 9, 2147483647, 1234567 are eligible as
Integer. We can create this as function and can use this.
CREATE TABLE MY_TABLE(MY_FIELD VARCHAR(50))
INSERT INTO MY_TABLE
VALUES('9.123'),('1234567'),('9'),('2147483647'),('2147483647.01'),('2147483648'), ('2147483648ABCD'),('214,7483,648')
SELECT *
FROM MY_TABLE
WHERE CHARINDEX('.',MY_FIELD) = 0 AND CHARINDEX(',',MY_FIELD) = 0
AND ISNUMERIC(MY_FIELD) = 1 AND CONVERT(FLOAT,MY_FIELD) / 2147483647 <= 1
DROP TABLE MY_TABLE
I did it using a Case statement:
Cast(Case When Quantity/[# of Days]= Cast(Quantity/[# of Days] as int) Then abs(Quantity/[# of Days]) Else 0 End as int)
To test whether the input value is an integer or not we can use SQL_VARIANT_PROPERTY function of SQL SERVER.
The following SQL Script will take input and test it whether the data type turns out to be integer or not
declare #convertedTempValue bigint, #inputValue nvarchar(255) = '1' --Change '1' to any input value
set #convertedTempValue = TRY_PARSE(#inputValue as bigint) --we trying to convert to bigint
declare #var3 nvarchar(255) = cast (SQL_VARIANT_PROPERTY(#convertedTempValue,'BaseType') as nvarchar(255)) --we using SQL_VARIANT_PROPERTY to find out datatype
if ( #var3 like '%int%')
begin
print 'value is integer'
end
else
begin
print 'value is non integer'
end
go
Really late to this but would this work?
select * from from table
where (ISNUMERIC(zipcode) = 0 OR zipcode like '%.%')
Filters out items that are integers.
Maybe you should only store integer data in integer datatypes.

Sql combine WHEN and IF statement with multiple parameters

How to combine Q1 and Q2 into someting like Q5 (But working!) ? Plse? I'M stuck... SQL Server 2008 R2
Please have a look what I've tried so far:
--Q1 does execute without errors:
DECLARE #RfDate date
DECLARE #Description nvarchar(250)
DECLARE #BAccount int
SET #RfDate = '{Rf_Date}'
SET #Description = {dbo.BankstatementLine_Description|type=string}
SET #BAccount = {dbo.BankAccount_Id}
IF #RfDate <> ''
BEGIN
SELECT *
FROM
dbo.BankStatementLine
WHERE
Date >=#RfDate
AND
FkBankAccount = #BAccount
AND
IsDebit = 'true'
AND
Id NOT IN (select FkBankStatementLine from DocumentBankStatementLine)
END
ELSE
BEGIN
SELECT *
FROM
dbo.BankStatementLine
WHERE
Date <> #RfDate
AND
FkBankAccount =#BAccount
AND
IsDebit = 'true'
AND
Id NOT IN (select FkBankStatementLine from DocumentBankStatementLine)
END
--Q2 does execute without errors:
DECLARE #RAmount float
SET #RAmount = {Rf_Amount}
IF #RAmount <>''
BEGIN
SELECT Amount
FROM dbo.BankStatementLine
WHERE Amount=#RAmount
END
ELSE
BEGIN
SELECT Amount
FROM dbo.BankStatementLine
WHERE Amount<>#RAmount
END
After the help from X-Zero (imperative describes my character better then my program skills btw), I came up with the following query which actually does what it needs to do, except for the last two AND OR rules. The LIKE does not have any influence, if I enter ‘PEKING’ in the field #RfAccept, the entries whith Description “0111111111 GPPeking” should be presented, but is does not.....
:
DECLARE #RfDate date
DECLARE #BAccount int
DECLARE #RfAmount decimal
DECLARE #RfAcAmount float
DECLARE #RfKenmerk nvarchar(250)
DECLARE #RfAccept nvarchar(250)
SET #RfDate = '{Rf_Date}'
SET #BAccount = {dbo.BankAccount_Id}
SET #RfAmount = {Rf_Amount}
SET #RfAcAmount = {Rf_AccAmount}
SET #RfKenmerk = {Rf_Betalingskenmerk|type=string}
SET #RfAccept = {Rf_Acceptgiro|type=string}
SELECT *
FROM
dbo.BankStatementLine
WHERE -- All statements can have a value or ''. All statements are not mandatory.
isDebit = 1
AND Id NOT IN (select FkBankStatementLine from DocumentBankStatementLine)
AND fkBankAccount = {dbo.bankAccount_Id}
AND ((Date = #RfDate AND #RfDate <> '')
OR (Date <> #RfDate AND #RfDate = ''))
AND ((Amount = #RfAmount AND #RfAmount <> '')
OR (Amount <> #RfAmount AND #RfAmount = ''))
AND ((Amount = #RfAcAmount AND #RfAcAmount <> '')
OR (Amount <> #RfAcAmount AND #RfAcAmount = ''))
AND((Description LIKE '%#RfAccept%' AND #RfAccept<>'')--When Rf_Acceptgiro has a value, the value must be part of the field Description.
OR (Description <> #RfAccept AND #RfAccept ='')) --OR Return all Description rules
AND((Description LIKE '%#RfKenmerk%' AND #RfKenmerk<>'')--When Rf_Kenmerk has a value, the value must be part of the field Description.
OR (Description <> #RfKenmerk AND #RfKenmerk =''))--OR Return all Description rules
... You seem to have some issues with (not fully) understanding SQL, and all it can do in just general use. These kinds of 'procedures' are generally (although not always) unnecessary. You haven't listed your RDBMS, so I'm writing as if for DB2 (excluding statement parameters), although most major RDBMSs will be able to run the statements largely as is.
-Q1 can be simply re-written as so:
SELECT a.* -- note, make sure to list all columns in actual query, '*' is bad form
FROM dbo.BankStatementLine as a
EXCEPTION JOIN DocumentBankStatementLine as b
ON b.fkBankStatementLine = a.id -- this is your 'NOT IN' statement
WHERE a.isDebit = 'true' -- this is really bad; usea boolean type if available
-- otherwise, use `int`/`char` 1/0, with check constraints
AND a.fkBankAccount = {dbo.bankAccount_id}
AND (({Rf_Date} IS NOT NULL AND a.Date >= {Rf_Date}) -- please name 'a.date' better...
OR ({Rf_Date} IS NULL AND a.Date IS NULL)) -- and use `date` types, and -null-
-Q2 follows the same general principles (although it seems pointless; you already know the amount):
SELECT amount -- it's -really- bad to use `float` types for money
-- use `decimal` or `int` (cents) types instead
FROM dbo.BankStatementLine
WHERE (({Rf_Amount} IS NOT NULL AND amount = {Rf_Amount})
OR ({Rf_Amount} IS NULL AND amount IS NULL))
-Q3 seems to be a combination of Q1 and Q2 (sort of):
SELECT a.*
FROM dbo.BankStatementLine as a -- unless there's a -need- to query a specific
-- schema, leave it off; you'll get a bit of flexibility
EXCEPTION JOIN DocumentBankStatementLine as b
ON b.fkBankStatementLine = a.id
WHERE a.isDebit = 'true'
AND a.fkBankAccount = {dbo.bankAccount_Id} -- this seems like a table name?
AND (({Rf_Date} IS NOT NULL AND a.Date >= {Rf_Date})
OR ({Rf_Date} IS NULL AND a.Date IS NULL))
AND (({Rf_Amount} IS NOT NULL AND amount = {Rf_Amount}) -- didn't know what you
OR ({Rf_AccAmount} IS NOT NULL AND amount = {Rf_AccAmount})) -- actually wanted
-- But `null`s don't compare to anything, so...
-Q4: I'm not sure you can actually nest if statements that way (especially the Amount-(IF #RAmount <> '') line, and you definitely shouldn't. It's also unclear (because of Q3) whether the ordering is important, so I've assumed it is. Try this instead (please note that this, and your original version, only work if there's one row returned):
SELECT *
FROM dbo.BankStatementLine
WHERE amount = COALESCE({RF_Amount}, {RfAccAmount}, (SELECT amount
FROM dbo.BankStatementLine
WHERE amount IS NOT NULL))
-Q5 seems to be some wierd conglomeration of Q3 and Q1. The same re-writable rules apply though... And if you want to combine Q2 and Q1, simply add together the missing predicates from the WHERE clauses (for our purposes, EXCEPTION JOINs are considered WHERE clause predicates):
SELECT a.*
FROM dbo.BankStatementLine as a
EXCEPTION JOIN DocumentBankStatementLine as b
ON b.fkBankStatementLine = a.id
WHERE a.isDebit = 'true'
AND a.fkBankAccount = {dbo.bankAccount_Id}
AND (({Rf_Date} IS NOT NULL AND a.Date >= {Rf_Date})
OR ({Rf_Date} IS NULL AND a.Date IS NULL))
AND (({Rf_Amount} IS NOT NULL AND amount = {Rf_Amount})
OR ({Rf_Amount} IS NULL AND amount IS NULL))
Nesting if statements/clauses is always slightly treacherous, even in normal imperative (Java, C#, C++, etc) languages. In SQL and similar, it's probably just plain wrong. You seem to be thinking too much like an imperative programmer - learn to think in sets (your WHERE and JOIN clauses), and you'll be much better off.
EDIT:
It's not returning the results you expect, because the comparison is case sensitive. This is generally true of most other programming languages, as well.
As a side note, doing a LIKE '%<insertValueHere>' (with a leading %) prevents indicies from being used (because there's no good way for the optimizer to know where in the column the value appears). Wrapping the column in a function isn't going to help much, either, but I believe there are ways to create 'materialized'/computed indicies, such that the value is already available.
In any case, here's the appropriate adjustments. Please note that, if a column will always have a value (as opposed to null), you don't need to do a comparison if the input parameter isn't provided.
DECLARE #RfDate date
DECLARE #BAccount int
DECLARE #RfAmount decimal
DECLARE #RfAcAmount float
DECLARE #RfKenmerk nvarchar(250)
DECLARE #RfAccept nvarchar(250)
SET #RfDate = '{Rf_Date}'
SET #BAccount = {dbo.BankAccount_Id}
SET #RfAmount = {Rf_Amount}
SET #RfAcAmount = {Rf_AccAmount}
SET #RfKenmerk = {Rf_Betalingskenmerk|type=string}
SET #RfAccept = {Rf_Acceptgiro|type=string}
SELECT *
FROM dbo.BankStatementLine
WHERE isDebit = 1 -- Thank you, this is much better. If numeric, add check constraint.
AND Id NOT IN (select FkBankStatementLine from DocumentBankStatementLine)
-- I am unsure of the performance of this relative to other options
AND fkBankAccount = {dbo.bankAccount_Id}
-- Assuming this is an actual date field, non-nullable, you don't need the second comparison
AND ((Date = #RfDate AND #RfDate <> '')
OR (#RfDate = ''))
-- Don't store amounts as strings, just don't...
-- Comparison removed for reason above.
AND ((Amount = #RfAmount AND #RfAmount <> '')
OR (#RfAmount = ''))
-- See notes above
AND ((Amount = #RfAcAmount AND #RfAcAmount <> '')
OR (#RfAcAmount = ''))
-- If you want all rules/whatever, then...
-- If it's case insensitive, it's best to -store- it that way. Otherwise, wrap in function
AND((UPPER(Description) LIKE '%' || UPPER(#RfAccept) || '%' AND #RfAccept<>'')
OR (#RfAccept =''))
-- Same thing here too.
AND((Description LIKE '%#RfKenmerk%' AND #RfKenmerk<>'')
OR (#RfKenmerk =''))
When you're inputting a parameter that says, "I don't care what it is, give me everything", the comparison with the field isn't needed (and you may get better performance by removing the comparison). If you still have to check to make sure the field isn't null or blank or something, then you do have to check it at some point - either in the SQL, or after getting the result set.
Also, if you're searching inside the field with LIKE '%whatever' because it contains multiple values (either as a delimiter/formatted list, or a datastructure), you (most likely) have the tables set up incorrectly; reformat to put the column in it's own table(s) (well, _usually). If it's part of the thing (like searching for a word in a book title), you just have to take the performance hit (well, there are maybe ways around this, but result in somewhat wacky designs).
Looks like you're working with SQL Server (it usually helps to specify):
Amount = CASE WHEN #RAmount <> '' THEN #RAmount
WHEN #RAcAmount <> '' THEN #RacAmount
ELSE Amount END
is what I think you're looking for. If the first parameter is not empty, then use it. If the first parameter is empty, and the second one is not, then use the second one. If both are empty, then return all values.

An expression of non-boolean type specified in a context where a condition is expected, near 'END'

So maybe someone can point me in the right direction of what is causing this error? I've been fighting with this for a couple of hours and searching the web, and I can't figure out what I'm doing wrong here. It's included as part of a stored procedure, I don't know if that matters, if it does I can include that as well. Tables and field names have been changed to protect the innocent... meaning my job. Thanks.
SELECT
/* The fields are here*/
FROM
/* my joins are here */
WHERE
(Table.Field = stuff)
AND
(Table.Field2 = otherstuff)
AND
(Table2.Field3 = someotherstuff)
AND
CASE #param1
WHEN 0 THEN 'Table.Field IS NULL'
WHEN 1 THEN 'Table.Field2 IS NOT NULL'
ELSE ''
END
Thanks for the responses. Technically egrunin was the correct answer for this question, but OMG Ponies and Mark Byers were pretty much the same thing just missing that last piece. Thanks again.
I'm pretty sure the other answers leave out a case:
WHERE
(Table.Field = stuff)
AND
(Table.Field2 = otherstuff)
AND
(Table2.Field3 = someotherstuff)
AND
(
(#param1 = 0 and Table.Field IS NULL)
OR
(#param1 = 1 and NOT Table.Field2 IS NULL)
OR
(#param1 <> 0 AND #param1 <> 1) -- isn't this needed?
)
You are returning a string from your case expression, but only a boolean can be used. The string is not evaluated. You could do what you want using dynamic SQL, or you could write it like this instead:
AND (
(#param1 = 0 AND Table.Field IS NULL) OR
(#param1 = 1 AND Table.Field IS NOT NULL)
)
You can't use CASE in the WHERE clause like you are attempting
The text you provided in the CASE would only run if you were using dynamic SQL
Use:
WHERE Table.Field = stuff
AND Table.Field2 = otherstuff
AND Table2.Field3 = someotherstuff
AND ( (#param1 = 0 AND table.field IS NULL)
OR (#param1 = 1 AND table.field2 IS NOT NULL))
...which doesn't make sense if you already have Table.Field = stuff, etc...
Options that would perform better would be to either make the entire query dynamic SQL, or if there's only one parameter - use an IF/ELSE statement with separate queries & the correct WHERE clauses.

Best equivalent for IsInteger in SQL Server

What is the best way to determine whether or not a field's value is an integer in SQL Server (2000/2005/2008)?
IsNumeric returns true for a variety of formats that would not likely convert to an integer. Examples include '15,000' and '15.1'.
You can use a like statement but that only appears to work well for fields that have a pre-determined number of digits...
select * where zipcode like '[0-9][0-9][0-9][0-9][0-9]'
I could write a user defined function that attempts to convert a varchar parameter to an int within a try/catch block but I'm checking with the community to see if someone has come across any succient methods to achieve this goal - preferably one that can be used within the where clause of a SQL statement without creating other objects.
Late entry that handles negative
ISNUMERIC(zipcode + '.0e0') --integer
ISNUMERIC(zipcode + 'e0') --decimal
For more see this
1 approach is
zipcode NOT LIKE '%[^0-9]%'
Double negatives, got to love 'em!
If SQL Server 2005+, I'd enable CLR and create the function to support regexes. For SQL Server 2000, see this article for creating a UDF to do the same thing.
Then I'd use the regex: ^\d{5}$
This expression gives 1 for an integer value and 0 otherwise
floor((floor(abs(zipcode)))/abs(zipcode))
Why not just use the following? I can't see to find any cases where it fails.
1 = integer
0 = not integer
null = non-numeric
DECLARE #TestValue nvarchar(MAX)
SET #TestValue = '1.04343234e5'
SELECT CASE WHEN ISNUMERIC(#TestValue) = 1
THEN CASE WHEN ROUND(#TestValue,0,1) = #TestValue
THEN 1
ELSE 0
END
ELSE null
END AS Analysis
It looks like this question needs an updated answer.
Limiting the answer to the question title:
where ISNUMERIC(zipcode) = 1
and zipcode - FLOOR(zipcode) = 0
Expounding based on the text of the question...
Currently-supported versions of SQL Server all support/include the TRY-CONVERT function.
declare #a varchar(100)
set #a = '-1.2a'
--set #a = '-1.2'
--set #a = '-1'
--set #a = '-1.0'
--set #a = '-0'
--set #a = '0'
--set #a = '1'
select #a as 'Value'
, ISNUMERIC(#a) as ISNUMERIC
, case when ISNUMERIC(#a) = 1 and #a - FLOOR(#a) = 0 then 1 else 0 end as ISINTEGER
, case when try_convert(int, #a) >= 0 and left(#a, 1) <> '-' then 1 else 0 end as ISWHOLENUMBER
, case when try_convert(int, #a) > 0 then 1 else 0 end as ISCOUNTINGNUMBER
You'll notice that TRY_CONVERT(INT, -1.0) returns NULL. So TRY_CONVERT(INT, #a) IS NOT NULL is not quite right for ISINTEGER.
case when ISNUMERIC(#a) = 1 and #a - FLOOR(#a) = 0 then 1 else 0 end as ISINTEGER
...works because if ISNUMERIC(#a) = 1 is false, FLOOR(#a) is not evaluated. Reversing the order...
case when #a - FLOOR(#a) = 0 and ISNUMERIC(#a) = 1 then 1 else 0 end as ISINTEGER
...generates an error when the value (#a) is not numeric.
So, for the case of zipcode, assuming you want to verify that a 5-digit zip code is a number and it must be 5 digits (so it can't be zero or less) and would never contain a decimal point (so you don't need to know if 12345.000 is an integer):
where try_convert(int, zipcode) > 0
and len(zipcode) = 5
I came up with the perfect answer for this on another StackO question.
It also proves you cannot use ".0e0" like one user suggests here.
It does so without CLR or non-scalar functions.
Please check it out: https://stackoverflow.com/a/10645764/555798
After moving to sql 2008, I was struggling with isnumeric('\8') returning true but throwing an error when casting to an integer. Apparently forward slash is valid currency for yen or won - (reference http://www.louiebao.net/blog/200910/isnumeric/)
My solution was
case when ISNUMERIC(#str) > 0 and not rtrim(#str) LIKE '[^0-9]%' and not rtrim(#str) LIKE '%[^0-9]' and not rtrim(#str) LIKE '[^0-9]%' then rtrim(#str) else null end
See whether the below code will help.
In the below values only 9, 2147483647, 1234567 are eligible as
Integer. We can create this as function and can use this.
CREATE TABLE MY_TABLE(MY_FIELD VARCHAR(50))
INSERT INTO MY_TABLE
VALUES('9.123'),('1234567'),('9'),('2147483647'),('2147483647.01'),('2147483648'), ('2147483648ABCD'),('214,7483,648')
SELECT *
FROM MY_TABLE
WHERE CHARINDEX('.',MY_FIELD) = 0 AND CHARINDEX(',',MY_FIELD) = 0
AND ISNUMERIC(MY_FIELD) = 1 AND CONVERT(FLOAT,MY_FIELD) / 2147483647 <= 1
DROP TABLE MY_TABLE
I did it using a Case statement:
Cast(Case When Quantity/[# of Days]= Cast(Quantity/[# of Days] as int) Then abs(Quantity/[# of Days]) Else 0 End as int)
To test whether the input value is an integer or not we can use SQL_VARIANT_PROPERTY function of SQL SERVER.
The following SQL Script will take input and test it whether the data type turns out to be integer or not
declare #convertedTempValue bigint, #inputValue nvarchar(255) = '1' --Change '1' to any input value
set #convertedTempValue = TRY_PARSE(#inputValue as bigint) --we trying to convert to bigint
declare #var3 nvarchar(255) = cast (SQL_VARIANT_PROPERTY(#convertedTempValue,'BaseType') as nvarchar(255)) --we using SQL_VARIANT_PROPERTY to find out datatype
if ( #var3 like '%int%')
begin
print 'value is integer'
end
else
begin
print 'value is non integer'
end
go
Really late to this but would this work?
select * from from table
where (ISNUMERIC(zipcode) = 0 OR zipcode like '%.%')
Filters out items that are integers.
Maybe you should only store integer data in integer datatypes.

sql query - true => true, false => true or false

Simple query, possibly impossible but I know there are some clever people out there :)
Given a boolean parameter, I wish to define my where clause to either limit a certain column's output - or do nothing.
So, given parameter #bit = 1 this would be the result:
where column = 1
given parameter #bit = 0 this would be the result:
where column = 1 or 0
i.e. have no effect/show all results (column is a bit field)
I'm not wanting dynamic sql - I can settle for fixing this in code but I just wondered if there's some clever magic that would make the above neat and simple.
Is there? I'm using sql server.
cheers :D
The answer column = 1 or #bit = 0 works if column may only be 0 or 1. If column may be any value you want: column = 1 or #bit = 0 and column = 0.
SELECT *
FROM mytable
WHERE column = 1 OR #bit = 0
If you have an index on column1, this one will be more efficient:
SELECT *
FROM mytable
WHERE column = 1 AND #bit = 1
UNION ALL
SELECT *
FROM mytable
WHERE #bit = 0
See this article in my blog for performance comparison of a single WHERE condition vs. UNION ALL:
IN with a comma separated list: SQL Server
where column BETWEEN #bit AND 1
select *
from MyTable
where (#bit = 0 OR MyColumn = 1)
select ...
from [table]
where #bit = 0 or (column = #bit)
I had come up with a different answer and felt dumb when seeing the consensus answer.
So, just for yucks, compared the two using my own database. I don't really know if they are really comparable, but my execution plans give a slight advantage to my goofy answer:
select *
from MyTable
where column <> case #bit when 1 then 0 else -1 end
I realize indices, table size, etc. can affect this.
Also, realized you probably can't compare a bit to a -1...
Just thought I'd share.
try this
select ...
from table
where column = case when #bit = 0 then 0 else column end
this works no matter what the datatype of column is (could even be a string, for example). If it were, of course, it would be a different default value (not 0)
WHERE column >= #bit
However, this only works for > 0 values in a numeric column. #bit will be implicitly cast to int, smallint etc because of data type precedence.