T-SQL match special characters. Pre should match Pré - sql-server

I have a list of company names and the user has to enter his company name to get into the system. Let's say we have the company "Pré ABC", now I want the user to be able to type "Pre" or "Pré".
First I thought this was build-in functionality of the LIKE statement, but unfortunately it isn't. Any thoughts?

This has to do with collation. Each database has its own collation (and any column can override that collation, too). In your case, you're looking for a collation that's not accent-sensitive, and not case-sensitive. Try configuring the database to "SQL_Latin1_General_CP1_CI_AI". That decodes as "code page 1, case-insensitive, accent-insensitive", which should make your queries work as desired.

SELECT 1
WHERE N'Pré ABC' COLLATE LATIN1_GENERAL_CI_AI LIKE N'%Pre%'

Related

Arabic name query returns more then one results

I have a situation when doing a simple select query with a specific arabic name like the following "رفعة" the query returns more then one results. It rightly returns "رفعة", but it also returns "رفعت".
SELECT * FROM Table where ArabicName = N'رفعة'
I have encountered two other situations as well. When querying with "حياة" it returns "حياة" and "حيات".
When querying with "نعمة" it returns "نعمة" and "نعمت".
I have searched online for answers, but without luck.
Has anyone encountered this situation before?
Your problem is related to collation and you should understand what that means especially last few letters in collation Arabic_100_CI_AS.
CI means case insensitive, also you have option to set CS which means case sensitive
AS means accent sensitive, same as case there is option AI which means accent insensitive
Well, this collation can be set on server, database, column level or you can explicitly search adding COLLATE command at the end of statement.
I was able to fix the issue by adding the following to the query: COLLATE Arabic_100_CI_AS
SELECT * FROM Table where ArabicName COLLATE Arabic_100_CI_AS = N'رفعة'
Nb! It did not work without specifying the _100_ in the collation specification.

SOQL Query - How to write a SOQL query by making a field to lowercase and compare?

Following query returns an error:
Query:
SELECT Id, FirstName, LastName, OwnerId, PersonEmail
FROM Account
WHERE lower(PersonEmail) = lower('abc.DEF#org.cOM')
API Response:
success: false
result: Dictionary
error: IntegrationError
title: "The JSON body contains an error"
message: "Salesforce returned the following error code: MALFORMED_QUERY"
detail: "
'%test%' and lower(PersonEmail) = lower('abc.DEF#org.cOM')
^
ERROR at Row:4:Column:54
Bind variables only allowed in Apex code"
Can't we use SQL functions in SOQL?
You do not need to change the text to lower case:
Comparisons on strings are case-sensitive for unique case-sensitive fields and case-insensitive for all other fields
EDIT: to put it another way, only specific fields are uniquely marked to be case sensitive. The rest aren't. Also, emails are stored as all lowercase by default. Also, try the LIKE comparison, which (I believe) is case insensitive even for case sensitive fields.
Can't we use SQL functions in SOQL?
No, you can't. SOQL is a Salesforce-specific dialect. Here's a decent list of what you can use: https://salesforce.stackexchange.com/questions/166372/all-functions-available-in-soql. And any comparison you make must be in field operator value style. You can't compare field value with another field's value (apart from primary / foreign keys... you could write formulas for that though). And you can't do "clever" weird queries WHERE 1=1 AND...
This is not too different from other SQL dialects really? To me SQL Server's date format "112" is equally strange as to you lack of LOWER. If you really want to have a lowercase value returned/displayed in UI you can make a formula field in SF (bit like adding a column to materialized view?) - but comparisons on it will still be case-insensitive and probably slower, full table search to run ultimately useless function instead of using indexes.
SOQL is case insensitive on database level (I believe it's called collation?). Any SELECTs you make will return hits ignoring case so you don't have to explicitly call LOWER() There are some exceptions to this but PersonEmail is not one of them:
If you have custom field marked as unique case sensitive (you could ask admin to build an automationt hat copies value from PersonEmail to such custom field but i don't think there's a point)
If you use Platform Encryption (a.k.a. Salesforce Shield) and used Deterministic Encryption method with case-sensitive option.

SQL would using between statement improve this?

I want to find out using a select statement what columns in a table share similar information.
Example: Classes table with ClassID, ClassName, ClassCode, ClassDescription columns.
This was part of my SQL class that I already turned in. The question asked "What classes are part of the English department?"
I used this Select statement:
SELECT *
FROM Classes
WHERE ClassName LIKE "English%" OR ClassCode LIKE "ENG%"
Granted we have only input one actual English course in this database, the end result was it executed fine and displayed everything for just the English class. Which I thought was a success since we did populate other non English courses in the database.
Anyways, I was told I should have used a BETWEEN statement.
I am just sitting here thinking they would both do what I needed them to do right?
I'm using SQL Server 2014
No, BETWEEN would probably be a bad idea here. BETWEEN doesn't allow wildcards and doesn't do any pattern matching in any RDBMS I've used. So you'd have to say BETWEEN 'ENG' AND 'English'. Except that doesn't return things like 'English I' (which would be after 'English' in a sorted list).
It would also potentially include something like 'Engineering' or 'Engaging Artistry', but that's a weakness of your existing query, too, since LIKE 'ENG%' matches those.
If you happen to be using a case-sensitive collation you add a whole new dimension of complexity. Your BETWEEN statement gets even more confusing. Just know that capital letters generally come before lower case letters, so 'ENGRAVING I' would be included but 'Engraving I' would not. Additionally, 'eng' would not be included. Note that case-insensitive collation is the default.
Also whats the difference when searching for null values in one table
and one column
column_name =''
or
column_name IS NULL
You're not understanding the difference between an empty string and null.
An empty string is explicit. It says "This field has a known value and it is a string of zero length."
A null string is imprecise. It means "unknown". It could mean "This value wasn't asked for," or "This value was not available," or "This value has not yet been determined," or "This values does not make sense for this record."
"What is this person's middle name?"
"He doesn't have one. See, his birth certificate has no middle name listed." --> Empty string
"I don't know. He never told me and I don't have any birth or identity record." --> NULL
Note that Oracle, due to backwards compatibility, treats empty strings as NULLs. This is explicitly against ANSI SQL, but since Oracle is that old and that's how it's always worked that's how it will continue to work.
Another way to look at it is the example I tend to use with numbers. The difference between 0 and NULL is the difference between having a bank account with $0 balance and not having a bank account at all.
Nothing can be said unless we see table and its data.Though don't use between.
Secondly first find which of the column is not null by design.Say for example ClassName cannot be null then there is no use using ClassCode LIKE "ENG%",just ClassName LIKE "English%" is enough,similarly vice versa is also true.
Thirdly you should use same parameter in both column.for example
ClassName LIKE "English%" OR ClassCode LIKE "English%"
see the difference.
Select * FROM Classes
Where ClassName LIKE "%English%"

SQL LIKE Operator doesn't work with Asian Languages (SQL Server 2008)

Dear Friends,
I've faced with a problem never thought of ever. My problem seems too simple but I can't find a solution to it.
I have a sql server database column that is of type NVarchar and is filled with standard persian characters. when I'm trying to run a very simple query on it which incorporates the LIKE operator, the resultset becomes empty although I know the query term is present in the table. Here is the very smiple example query which doesn't act corectly:
SELECT * FROM T_Contacts WHERE C_ContactName LIKE '%ف%'
ف is a persian character and the ContactName coulmn contains multiple entries which contain that character.
Please tell me how should I rewrite the expression or what change should I apply. Note that my database's collation is SQL_Latin1_General_CP1_CI_AS.
Thank you very much
Also, if those values are stored as NVARCHAR (which I hope they are!!), you should always use the N'..' prefix for any string literals to make sure you don't get any unwanted conversions back to non-Unicode VARCHAR.
So you should be searching:
SELECT * FROM T_Contacts
WHERE C_ContactName COLLATE Persian_100_CI_AS LIKE N'%ف%'
Shouldn't it be:
SELECT * FROM T_Contacts WHERE C_ContactName LIKE N'%ف%'
ie, with the N in front of the comparing string, so it treats it like an nvarchar?

Case-insensitive REPLACE() in SQL Server 2000

I have a field that contains strings such as 'Blah-OVER', 'Blah-OveR', etc. and want to select them without the 'over's. This only catches the first case (so to speak) and not the others:
SELECT field as "before", REPLACE(field, 'OVER', '') as "after"
How do I just get them all to say 'Blah-' (preserving the case of what's left) without attempting to cover every case combination with another nested REPLACE function?
Use a case insensitive collation:
SELECT field as "before", REPLACE(field COLLATE SQL_Latin1_General_Cp1_CI_AI
, 'OVER', '') as "after"
See COLLATE for list of collation names so you choose the one appropiate for your data.
Update
Ok, so I missed your actual request (change case of input, not find case-insensitive). The proper solution is... not to change the input but use an adequate collation for your data. If the data must be displayed in a specific format, use display options in the client, eg. CSS text-transform:uppercase, not in the server SELECT.
There isn't any built-in SQL function to do this transformation in-place, but is trivial to build a CLR function that uses RegEx. (On SQL 2005, not on SQL 2000... doh, I need more coffe).
I'm not familiar with SQL Server, but maybe it allows you to make use of regular expressions. These usually offer a case-insensitive mode (set via the i-flag).
Otherwise you could uppercase before the replace call, e.g.
SELECT field as "before", REPLACE(UPPER(field), 'OVER', '') as "after"

Resources