Column_name > " "? - sql

I came across a query today where inside an IIF statement there was a comparison where column > " ". I have never seen this before and I am not even sure what it is doing. I am familiar with comparing strings with < and >. IE "B" < "W" returns True.
However what exactly does comparing a column to a string of spaces do?
The line in the select statement:
,IIf([CD] > " " AND [DT]=#12/31/9999#,[MT],[O]) AS [Final]
Can someone explain exactly what this comparison is doing and why would you want this?

Your logic is checking that CD is larger than a field whose name consists only of spaces. That seems highly unlikely.
My guess is that you are either using MS Access because the date constant is not compatible with SQL Server. In SQL Server this would be:
IIf([CD] > ' ' AND [DT] = #12/31/9999#, [MT], [O]) AS [Final]
This is validating that the string does not start with a bunch of spaces. It is actually a rather pathetic way of doing this; more typically LTRIM() would be involved.
I might further speculate that CD is exactly five characters long. In this case, the logic is checking that it is not all spaces. This would be particularly applicable if the type were CHAR(5) NOT NULL.

Related

Difference between _%_% and __% in sql server

I am learning basics of SQL through W3School and during understanding basics of wildcards I went through the following query:
--Finds any values that start with "a" and are at least 3 characters in length
WHERE CustomerName LIKE 'a_%_%'
as per the example following query will search the table where CustomerName column start with 'a' and have at least 3 characters in length.
However, I try the following query also:
WHERE CustomerName LIKE 'a__%'
The above query also gives me the exact same result.
I want to know whether there is any difference in both queries? Does the second query produce a different output in some specific scenario? If yes what will be that scenario?
Both start with A, and end with %. In the middle part, the first says "one char, then between zero and many chars, then one char", while the second one says "one char, then one char".
Considering that the part that comes after them (the final part) is %, which means "between zero and many chars", I can only see both clauses as identical, as they both essentially just want a string starting with A then at least two following characters. Perhaps if there were at least some limitations on what characters were allowed by the _, then maybe they could have been different.
If I had to choose, I'd go with the second one for being more intuitive. After all, many other masks (e.g. a%%%%%%_%%_%%%%%) will yield the same effect, but why the weird complexity?
For Like operator a single underscore "_" means, any single character, so if you put One underscore like
ColumnName LIKE 'a_%'
you basically saying you need a string where first letter is 'a' then followed by another single character and then followed by anything or nothing.
ColumnName LIKE 'a__%' OR ColumnName LIKE 'a_%_%'
Both expressions mean first letter 'a' then followed by two characters and then followed by anything or nothing. Or in simple English any string with 3 or more character starting with a.

sas sql : filter out corrupted row

I need to copy data from own table to another and filter out corrupted rows;
I have a column with dates and sometimes I have rows like this " . " - random number of spaces and one dot.
how can I make my sql to ignore these rows?
i tried to make using
where (trim(put(DatesOfRun) not like '.'
and multiple other variance of
"where not like"
or
"where <>"
but all of them gave me an errors like
"Expression using equals (=) has components that are of different
data types."
or
ERROR 22-322: Syntax error, expecting one of the following:
and a long list of operators
First, you need to confirm if this is a character or a numeric field. . is how SAS displays null (missing in SAS speak) for numerics, so it's entirely possible you have a numeric field.
where not missing(DatesOfRun)
or
where DatesOfRun is not null
Either of those should do it, if it's numeric.
If it is character, then it's fairly simple.
where not (strip(DatesOfRun) = '.')
trim only trims blanks at the end, strip removes from both sides.
It's also possible you have non-breaking spaces or other things that are going to mess the latter up; if the strip one works as in doesn't error, but doesn't actually remove the characters, you may want to use a data step and put that variable to the log using $HEX32. format (with appropriate width, 2 times the number of characters possible), and see what comes out; if you don't recognize the characters or don't know how to handle ASCII codes, come back here and ask a new question with that information.
Just to clarify, you are trying to ignore results where the DatesOfRun column contains the character '.'? If so, you may want to use wildcard operators if the '.' can appear in random locations, such as '.%' or '%.%'
Also, check the datattype of the DatesOfRun column; this could influence results as well.
Two WHERE clauses could potentially solve your issue; try using this WHERE clause and see if it throws an error:
WHERE DatesOfRun is not null
AND DatesOfRun not like '%.%'

SQL string comparison -how to ignore blank spaces

I have prepared an SQL query that I will have to run on several databases (Oracle and Sybase) where some data might be stored differently.
I have noticed that one of the differences in data storage is the blank string.
For example, in the column PRODUCT_TYPE below, please have a look at the second record:
This "empty string" (the data type is CHAR(15)) circled in red is equal to '' in some of the databases, whereas it's equal to ' ' to some others. The length is never constant and there are several fields that behave as such.
So, since I need to filter on these "empty strings", I should change the following statement in my WHERE clause:
WHERE PRODUCT_TYPE = ''
...because the above will take the ' ' string as different than '' even if "functionally" speaking is not.
I would hence like to make the statement in a way that it "ignores white spaces", i.e. ' ' is equal to '' that is equal to ' ' etc.
How should I do this change in order to make it work?
I have tried the simple replacing approach:
WHERE REPLACE(PRODUCT_TYPE,' ','') = ''
...but it doesn't seem to work, probably because I should use a different character.
For sake of testing, inside the ' below there is a copied-pasted example of what I find in these "empty strings":
' '
Ideally, it should be a "non-specific SQL" solution since I will have to run the same query on both Oracle and Sybase RDBMS. Any idea?
You can use trim on the column.
where trim(product_type) is null
The above is not DBMS-independent, since Sybase does not provide the trim function.
However, the below approach will work both in Sybase and Oracle:
where rtrim(ltrim(product_type)) is null
You can use the replace statement you've tried but you should test for "is null" instead of =''
WHERE REPLACE(PRODUCT_TYPE,' ','') is null
See also:
null vs empty string in Oracle
The simple (and non-DBMS specific) answer is:
Do not use CHAR(15).
char(n) is a fixed length data type. So no matter what you store in there, the value will always be padded to the defined length. If you store a single character, the DBMS will store that single character and 14 spaces.
Change your columns to use varchar(15) and you should not have any problems.

Is this theoretically valid method to protect against SQL injections?

I know there are methods (escaping/ prepared statements) to protect against injections. However, for "fun", do you think the following method works?
Assume you are given a string. You get the string and add "space" between every character.
This way, even if there is a security breach somehow, commands will not make sense because adding the "space" invalidates them.
I understand there are performance issues and stuff... But in theory, will it work?
No.
SQL injection is defined as the modification of the intended SQL command. If even a single character is able to modify it (e. g., a single quote prematurely ends the string literal, resulting in a syntax error), it is considered an SQL injection.
Even though this is sort of an "opinion" based question I'm still going to answer. "No." :) This will not safeguard against all possible cases. Most likely it will simply make some forms of injection more difficult, but certainly not all. Here's why.
Introducing spaces will not properly solve the problem, in addition to rendering the data into a format that is unlikely to reflect what you really want to store. For example, some applications will introduce user input as integer values in database lookups.
Given:
SELECT * FROM table WHERE id=$user_input_value
User input:
1OR1=1
Rendered statement:
SELECT * FROM table WHERE id= 1 OR 1 = 1
This remains completely valid SQL and will return all rows in the table. Whitespace around the equals sign will be discarded.
This will break up any operator or keywords of more than one character. An attacker would need to cause damage using single characters separated by spaces. Let's see what we can do with that.
Assume a one-character column named c:
SELECT 1
FROM (VALUES (1234)) x(c)
WHERE c = '" + injectedSql + "'
Inject
' + c + '
which gives:
SELECT 1
FROM (VALUES (1234)) x(c)
WHERE c = '' + c + ''
Pwned.

Understanding a Microsoft Office Access SQL query with 'IIF'

On a larger project, I am migrating dozens of queries from a Microsoft Office Access database (MDB) to Oracle.
While I was able to understand nearly all of the insane constructs that are possible to write in Access, I failed on a single one.
The (simplified) query is:
SELECT *
FROM SomeTable
WHERE
Left(SomeField,3)=IIf(SomeParameter="GYM",Mid(SomeField,2,1)<>'0')
AND
Left(SomeField,3)=IIf(SomeParameter="GYM",Left(SomeField,3)<>'110')
Here, SomeField is a column in the table and SomeParameter is an input to the query.
What I do not understand is the WHERE part:
Why is the else part missing from the IIF statement?
Why is a string compared to the result of an <> operation (i.e. a boolean)?
Since it successfully runs in Access, the query is valid. I failed to even generate some test data that will pass the comparison.
Any hints on how to interpret the comparison?
As I said in a comment, I share the original questioner's puzzlement over this expression:
WHERE Left(SomeField,3)=IIf(SomeParameter="GYM",Mid(SomeField,2,1)<>'0')
Let's unpack that:
If SomeParameter = "GYM" return this:
Mid(SomeField,2,1)<>'0'
This is testing the second character in SomeField against the string "0", so it means that there's a badly designed field, in that the second character in that field has independent meaning. This will return true for all values where the 2nd character is anything but 0.
Whatever it returns (True or Null in the False case), it will be compared to this string:
Left(SomeField,3)
If The first three characters of SomeField happen to be "Yes" then it might very well produce a true comparison, since in Access/Jet/ACE, Yes and True and -1 are all equivalent, and string representations can be implicitly coerced.
So, this might return rows that look like this:
SomeParameter SomeField
GYM Yes sir, that's my baby
However, it really makes not a lot of sense, as the test of SomeField is circular. That is, you're comparing to the first 3 characters of the field in an instance in which a true comparison can only happen when the first three characters are "Yes", but you're in turn comparing those first three characters to a test for whether or not the 2nd character in the same field <> 0. In all cases where the first three characters are "Yes" then the second character will definitely not be "0" so you really only need to test the value of the first three characters.
I vote for incompetence on the part of the original developer.
From http://www.techonthenet.com/access/functions/advanced/iif.php
iif ( condition, value_if_true, value_if_false )
So it's like a ternary operator in C++/C# etc.Looks like they don't care about if the value is false.
Also, I wonder if they didn't screw up the logic :)
EDIT
I believe it returns Null if the false condition isn't specified.
In which case it would appear that they're setting a field to either true (when the condition <> is true) or null, when it's false.
Seems like an odd design to me
The first iif will return Null if SomeParameter<>"GYM", otherwise it will return True or False depending on the boolean evaluation of the expression Mid(SomeField,2,1)<>'0'.
Same logic for the second iif.
Let me guess....is that a query in the finance industry ? ;-)