Negating a string to be passed to mssql server - sql

I have a text field which acts a filter field. It checks for equals, contains and starts with. My problem is, with out changing any of my code, can I check for the 'does not contain', 'does not start with' and so on by just using the string i'm passing with something like '!' operator or "<>"?
for example:
I want to get all the records that do not have 'a' in them, so can I pass the string as "!a" or "<>a" or something so that I can get the required records? (I know these two don't work cause I tried.)

You have to use the keyword NOT, e.g.
SELECT * FROM Table WHERE Foo NOT LIKE '%bar%'

Please refer http://www.sqlservercentral.com/Forums/Topic1213442-338-1.aspx
Can solve with case in where clause

Related

how to filter text according to a large number of possible values of a LIKE operator in POSTGRESQL?

EDIT: I changed my example a bit because it was incorrect and misleading. Here is a more correct one (I hope so).
This is a complex problem to explain, so I'll try to be as clear as I can.
I have a CASE that returns a value according to a text filter by means of the LIKE operator.
I need to generate 1 column (class_of_event) with N possible values that classify one given string in N possible categories.
This set of values searched by the LIKE operator will be used again and again in the script, and will be update occasionally.
The script is more or less like this:
SELECT
event,
CASE
WHEN
event LIKE '%MURDER%' or
event LIKE '%KILL%' or
... --and so on with many other possible values...
event LIKE '%WAR%'
THEN 'VIOLENCE'
WHEN
event LIKE '%MARRIAGE%' or
event LIKE '%MARRIED%' or
... --and so on with many other possible values...
event LIKE '%WIFE%'
THEN 'RELATIONSHIP'
ELSE NULL
END class_of_event
FROM TABLE history_facts
I know I can use the pipe | instead of the OR operator, thus writing
CASE WHEN event LIKE '%MARRIAGE%|%MARRIED%|%WIFE%' THEN 'RELATIONSHIP' ELSE null END class_of_event
instead of the long list of OR operators.
Anyway this could turn out in a VERY LONG string, because I could be willing to enlarge the set of values to be looked for.
ALSO, this set of values will be used again in the (long) script, and it will be a problem if one day I'll have to rewrite them all coherently.
So I tried putting these values in the return value of a function:
CREATE OR REPLACE FUNCTION relationship_event()
RETURNS text AS
$$SELECT text '%MARRIAGE%|%MARRIED%|%WIFE%'$$ LANGUAGE sql IMMUTABLE PARALLEL SAFE;
and then using the following:
CASE WHEN event LIKE relationship_event() THEN 'RELATIONSHIP' ELSE null END class_of_event
This seemed a good solution because I could just define or update the function once at the beginning of the script and then use it everywhere I needed it.
The problem is that this method performs quite well in some cases and horribly in other cases.
So, is there a way to:
1) write a synthetic version of event LIKE 'a' OR event LIKE 'b' OR event LIKE 'c' OR...
2) and store the strings I am looking for in some "global variable" that I can rewrite only once and re-use everywhere in the script?
Thanks everybody, this is driving me crazy.
I think I can do this easily with SAS or Python, but can't achieve it on POSTGRESQL
I know I can use the pipe | instead of the OR operator, thus writing
No, you can not. LIKE does not support a pipe as an "or" operator.
You can simplify the expressions using an array:
SELECT event,
CASE
WHEN event ilike any (array['%MURDER%','%KILL%','%WAR%'])
then 'VIOLENCE'
WHEN event ilike any (array['%MARRIAGE%','%MARRIED%','%WIFE%'])
then 'RELATIONSHIP'
END as class_of_event,
class_of_event
FROM history_facts;
You can put this into a function:
create or replace function map_event(p_input text)
returns text
as
$$
select CASE
WHEN event ilike any (array['%MURDER%','%KILL%','%WAR%'])
then 'VIOLENCE'
WHEN ilike any (array['%MARRIAGE%','%MARRIED%','%WIFE%'])
then 'RELATIONSHIP'
END;
$$
language sql
immutable;
Then you just need to call the function, rather having the CASE expression:
select event,
map_event(event) as class_of_event
from history_facts;

SQL request to find item in table by value in column

Its pretty simple question, I know, but I really stacked with a problem with it...
I have a table customer_customer and a column code in it. So I need to find all items with a specific code value. So I wrote that:
SELECT * FROM customer_customer WHERE code LIKE "КL-12345"
and got an error:
column "КL-12345" does not exist
Why КL-12345 became a column if I specify it as value of code column? What am I doing wrong?
String literals must be enclosed in single quotes.
By enclosing it in double quotes, you specified a variable name.
Also, note that your where condition is the same as writing
where code = 'КL-12345'
LIKE is used for pattern matching. For instance you would match all codes that contain 'KL-12345' like this
where code like '%KL-12345%'
Change it to single quotes
SELECT * FROM customer_customer WHERE code LIKE 'КL-12345'
or
SELECT * FROM customer_customer WHERE code = 'КL-12345'

How does the Like predicate work in SQL?

I have a field called OrderNumber and there's already a record with that field value of "JY8023".
I tried querying using this SQL code, but it returned nothing.
SELECT .... WHERE OrderNumber LIKE "JY8023"
I also tried using wildcards and it worked
SELECT .... WHERE OrderNumber Like "%JY8023%"
So does that mean OrderNumber Like "JY9023" is not the same as OrderNumber = "JY8023"?
the string has characters before or after it, that you can't see. try something like select length(OrderNumber) WHERE OrderNumber Like "%JY8023%" to confirm this. Some characters are not only invisible, but unselectable with a cursor. But, they're there and they affect string comparisons.
additional debugging steps to follow will be to use substring to extract the offending part, and other string functions to further inspect the value. like, maybe selecting the string as a hex encoded string will help you identify the bytes.

Is there a way to use the LIKE operator from an entity framework query?

OK, I want to use the LIKE keyword from an Entity Framework query for a rather unorthodox reason - I want to match strings more precisely than when using the equals operator.
Because the equals operator automatically pads the string to be matched with spaces such that col = 'foo ' will actually return a row where col equals 'foo' OR 'foo ', I want to force trailing whitespaces to be taken into account, and the LIKE operator actually does that.
I know that you can coerce Entity Framework into using the LIKE operator using .StartsWith, .EndsWith, and .Contains in a query. However, as might be expected, this causes EF to prefix, suffix, and surround the queried text with wildcard % characters. Is there a way I can actually get Entity Framework to directly use the LIKE operator in SQL to match a string in a query of mine, without adding wildcard characters? Ideally it would look like this:
string usernameToMatch = "admin ";
if (context.Users.Where(usr => usr.Username.Like(usernameToMatch)).Any()) {
// An account with username 'admin ' ACTUALLY exists
}
else {
// An account with username 'admin' may exist, but 'admin ' doesn't
}
I can't find a way to do this directly; right now, the best I can think of is this hack:
context.Users.Where(usr =>
usr.Username.StartsWith(usernameToMatch) &&
usr.Username.EndsWith(usernameToMatch) &&
usr.Username == usernameToMatch
)
Is there a better way? By the way I don't want to use PATINDEX because it looks like a SQL Server-specific thing, not portable between databases.
There isn't a way to get EF to use LIKE in its query, However you could write a stored procedure that finds users using LIKE with an input parameter and use EF to hit your stored procedure.
Your particular situation however seems to be more of a data integrity issue though. You shouldn't be allowing users to register usernames that start or end with a space (username.Trim()) for pretty much this reason. Once you do that then this particular issue goes away entirely.
Also, allowing 'rough' matches on authentication details is beyond insecure. Don't do it.
Well there doesn't seem to be a way to get EF to use the LIKE operator without padding it at the beginning or end with wildcard characters, as I mentioned in my question, so I ended up using this combination which, while a bit ugly, has the same effect as a LIKE without any wildcards:
context.Users.Where(usr =>
usr.Username.StartsWith(usernameToMatch) &&
usr.Username.EndsWith(usernameToMatch) &&
usr.Username == usernameToMatch
)
So, if the value is LIKE '[usernameToMatch]%' and it's LIKE '%[usernameToMatch]' and it = '[usernameToMatch]' then it matches exactly.

SQL to return results for the following regex

I have the following regular expression:
WHERE A.srvc_call_id = '40750564' AND REGEXP_LIKE (A.SRVC_CALL_DN, '[^TEST]')
The row that contains 40750564 has "TEST CALL" in the column SRVC_CALL_DN and REGEXP_LIKE doesn't seem to be filtering it out. Whenever I run the query it returns the row when it shouldn't.
Is my regex pattern wrong? Or does SQL not accept [^whatever]?
The carat anchors the expression to the start of a string. By enclosing the letters T, E, S & T in square brackets you're searching, as barsju suggests for any of these characters, not for the string TEST.
You say that SRVC_CALL_DN contains the string 'TEST CALL', but you don't say where in the string. You also say that you're looking for where this string doesn't match. This implies that you want to use not regexp_like(...
Putting all this together I think you need:
AND NOT REGEXP_LIKE (A.SRVC_CALL_DN, '^TEST[[:space:]]CALL')
This excludes every match from your query where the string starts with 'TEST CALL'. However, if this string may be in any position in the column you need to remove the carat - ^.
This also assumes that the string is always in upper case. If it's in mixed case or lower, then you need to change it again. Something like the following:
AND NOT REGEXP_LIKE (upper(A.SRVC_CALL_DN), '^TEST[[:space:]]CALL')
By upper-casing SRV_CALL_DN you ensure that you're always going to match but ensure that your query may not use an index on this column. I wouldn't worry about this particular point as regular expressions queries can be fairly poor at using indexes anyway and it appears as though SRVC_CALL_ID is indexed.
Also if it may not include 'CALL' you will have to remove this. It is best when using regular expressions to make your match pattern as explicit as possible; so include 'CALL' if you can.
Try with '^TEST' or '^TEST.*'
Your regexp means any string not starting with any of the characters: T,E,S,T.
But your case is so simple, starts with TEST. Why not use a simple like:
LIKE 'TEST%'