Case sensitivity goes crazy - sql-server

I have a database and I am trying to execute the following query:
SELECT COUNT(*) FROM [Resource] WHERE Name LIKE 'ChinaApp%'
SELECT COUNT(*) FROM [Resource] WHERE Name LIKE 'Chinaapp%'
This is returning 2 different counts:
The first thing that came to my mind is to check the case sensitivity. I checked the collation on the server level, the database level and the column level:
Server level : Latin1_General_CI_AS
SELECT SERVERPROPERTY('COLLATION')
Database level : Danish_Norwegian_CI_AS
SELECT DATABASEPROPERTYEX('Data Warehouse', 'Collation')
Column level : Danish_Norwegian_CI_AS
SELECT TABLE_NAME, COLUMN_NAME, COLLATION_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'Resource'
AND COLUMN_NAME = 'Name'
Question :
What is going wrong with the query? The case sensitivity is disabled as proven before. Why the counts are different?

Danish_Norwegian_CI_AS is the issue! Thank you #realspirituals for the hint!
In this default collation I have, 'aa' is actually one single character. The last line in the following link explain it. Å, å, AA, Aa and aa are all the same.
Collation chart for Danish_Norwegian_CI_AS
The following queries now provide the correct result set (count):
SELECT COUNT(*) FROM [Resource] WHERE Name LIKE 'ChinaApp%'
and
SELECT COUNT(*) FROM [Resource] WHERE Name LIKE 'Chinaapp%'
COLLATE Latin1_General_CI_AS

Try this:
SELECT COUNT ( * ) FROM [RESOURCE] WHERE Name COLLATE SQL_Latin1_General_CI_AS LIKE 'Chinaapp%'

Related

get the data type of columns in a select query

I know that you can get the type of a table's columns using the query below.
select COLUMN_NAME, DATA_TYPE
from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME = 'myTbl'
I was wondering if when you write a select query which involves 2 tables or more whether you can do something similar? I.e. is there a way to determine the column data types?
Just another option is sys.dm_exec_describe_first_result_set()
The nice thing about this is you can supply virtually any query, table, view, or even a stored procedure.
Example
Select column_ordinal
,name
,system_type_name
From sys.dm_exec_describe_first_result_set('Exec [dbo].[prc-App-Lottery-Search] ''7613''',null,null )
Returns
column_ordinal name system_type_name
1 DrawDate date
2 DrawDE varchar(1)
3 DrawAct varchar(4)
4 DrawNrm varchar(4)
5 Hits int
6 Elapsed nvarchar(4000)
Generic Example to see all columns available
Select *
From sys.dm_exec_describe_first_result_set('Select * from master..spt_values',null,null )
You can do this:
select COLUMN_NAME, DATA_TYPE
from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME IN ('myTbl1','myTbl2')
I used the below query to know all details about the columns in the table (shorter than selecting all columns)
describe tableName;

Select field_name base on the table id from each of the list

I have a problem.
I want to show field_name at my query 'select .. from .. where' clause.
In my logging table, the table only keep the [date],[table_id],[field_id] .. fields, i need to show the 'field_name' as well in my select but there is no any other table that i can 'join' to get the [field_name] based on [field_id] in my 'select .. from'. As I search from google it seems I can get the field_name from SQL system called 'sys.columns' table. but that is too complicated for my SQL level because this sys.coloums is not straight forward. it mixed all the table before all each field number depend on the table id itself.
anyone who know how to write a good query to select out the field_name pls help :)
log_list table
[date],[table_id],[field_id],[company_name],...
my current query :
SELECT
date , table_id , name as table_name
FROM
log_list join table_name_list on log_list.table_id = table_name_list.table_id
and log_list.company_name like '%something%'
WHERE
date between #startdate and #enddate
thank you for your attention.
Your tag didn't say what version of SQL Server you are using, assuming you are using 2008+ there is a system function
COL_NAME ( table_id , column_id )
which if you supply table_id and column_id would get you the name, for detailed reference check it out here: COL_NAME (Transact-SQL)
If that is not a valid option for you, look closer to sys.columns, the object_id it returns is actually the table's object_id and should be your table_id, so if you do something like following it should work:
select C.name AS column_name
...
FROM ...
...
join sys.columns C on yourtable.table_id = C.object_id and yourtable.column_id = C.column_id

unexpected output sql server using count

I am using sql-server 2012
The query is :
CREATE TABLE TEST ( NAME VARCHAR(20) );
INSERT TEST
( NAME
)
SELECT NULL
UNION ALL
SELECT 'James'
UNION ALL
SELECT 'JAMES'
UNION ALL
SELECT 'Eric';
SELECT NAME
, COUNT(NAME) AS T1
, COUNT(COALESCE(NULL, '')) T2
, COUNT(ISNULL(NAME, NULL)) T3
, COUNT(DISTINCT ( Name )) T4
, COUNT(DISTINCT ( COALESCE(NULL, '') )) T5
, ##ROWCOUNT T6
FROM TEST
GROUP BY Name;
DROP TABLE TEST;
In the result set ther is no 'JAMES' ? (caps)
please tell how this was excluded
expected was Null,james,JAMES,eric
You need to change your Name column collation to Latin1_General_CS_AS which is case sensitive
SELECT NAME COLLATE Latin1_General_CS_AS,
Count(NAME) AS T1,
Count(COALESCE(NULL, '')) T2,
Count(Isnull(NAME, NULL)) T3,
Count(DISTINCT ( Name )) T4,
Count(DISTINCT ( COALESCE(NULL, '') )) T5,
##ROWCOUNT T6
FROM TEST
GROUP BY Name COLLATE Latin1_General_CS_AS;
Use a sensitive case collation like COLLATE Latin1_General_CS_AS.
CREATE TABLE TEST ( NAME VARCHAR(20) COLLATE Latin1_General_CS_AS );
The other people who commented here are correct.
It would be easier for you to understand their meaning if you googled for collation and case sensitivity, but in layman's terms it's like this:
Collation is a little like encoding; It determines how the characters in string columns are interpreted, ordered and compared to one another. Case insensitive means that UPPERCASE / lowercase are considered exactly the same, so for instance 'JAMES', 'james', 'JaMeS' etc would be no different to SQL Server. So when your database has a case-insensitive collation and you then create a table with a column without defining the collation, that column will inherit the default collation used by the database, which is how we arrived here.
You can manually alter a column collation, or define it during a query, but bear in mind that whenever you compare two different columns, you need to assign both of them to use the same collation, or you will get an error. That's why it's good practice to pretty much use the same collation throughout the database barring special query-specific circumstances.
To your question regarding what Latin1_General_CS_AS means, it basically means "Latin1_General" alphabet, the details of which you can check online. The "CS" part means case-sensitive, if it were case-insensitive you would see "CI" instead. The "AS" means accent-sensitivity, and "AI" would mean accent-insensitivity. Basically, whether 'Á' is considered to be equal to 'A', or not.
You can read a lot more about it from the source, here.

Cannot resolve the collation conflict between "Latin1_General_CI_AI" and "SQL_Latin1_General_CP1_CI_AS" in the equal to operation

I am trying to create a procedure in SQL Server 2008R2 but it is showing this error
Cannot resolve the collation conflict between "Latin1_General_CI_AI"
and "SQL_Latin1_General_CP1_CI_AS" in the equal to operation.
The procedure that I have created is
CREATE Procedure Ps_Quiz_OnlineTest_QuestionsWithOptions_Get --'Ques1'
#Ques Varchar(8000)
As
Begin
Select
A.QuestionId,
A.QsnDesc,
A.CorrectOption,
B.OptionValue,
A.Marks,
(
Select QsnName
From Quiz_tblQsnsLimitMaster
Where QsnId = #Ques) QuesPaper,
(
Select Durationoftest
From Quiz_tblQsnsLimitMaster
Where QsnId = #Ques) QuesPaper
From
Quiz_tblQsnCreationMaster A,
Quiz_tblQsnCreationDetail B
Where
A.QuestionId = B.QuestionId
And A.QuestionId In (
Select QuestionIds
From FN_Question_Answers_Quiz(#Ques))
And B.QuestionId In (
Select QuestionIds
From FN_Question_Answers_Quiz(#Ques))
Order By
A.QuestionId,
B.OptionOrder
End
I tried to collate tables with different collations but it did not worked.
How can I solve this.
probably this might help, change your where condition like this
Where A.QuestionId COLLATE DATABASE_DEFAULT = B.QuestionId COLLATE DATABASE_DEFAULT
Since you've mentioned that QuestionID in each table is varchar, it's probably the comparison between those. So at a guess, try changing the line:
Where A.QuestionId = B.QuestionId And
To the following:
Where A.QuestionId = B.QuestionId COLLATE SQL_Latin1_General_CP1_CI_AS And
I'd prefer it if you used proper join syntax for your tables - but that's for another day ;-)
try use this,
where fieldname COLLATE DATABASE_DEFAULT = secondfieldname COLLATE DATABASE_DEFAULT
this is working
Just use the following syntax when joining tables with different collations,
where A.QuestionId collate SQL_Latin1_General_CP1_CI__AS = B.QuestionId collate
SQL_Latin1_General1_General_CP1_CI_AS
To overcome this use the below code:
SELECT NAME
FROM sys.objects
WHERE NAME COLLATE DATABASE_DEFAULT NOT IN (SELECT TYPE
FROM sys.objects)
I was facing same issue after migration of Database and shifting of server by service provider. So as solution I have created new database using CPanel then execute SQL query for schema and data to restore. Finally this issue got resolved.

SQL change field Collation in a select

i'm trying to do the following select:
select * from urlpath where substring(urlpathpath, 3, len(urlpathpath))
not in (select accessuserpassword from accessuser where accessuserparentid = 257)
I get the error:
Cannot resolve the collation conflict between
"SQL_Latin1_General_CP1_CI_AI" and
"SQL_Latin1_General_CP1_CI_AS" in the equal to operation.
Does anyone know how i can cast as a collation, or something that permits me to match this condition?
Thanx
You can add COLLATE CollationName after the column name for the column you want to "re-collate". (Note: the collation name is literal, not quoted)
You can even do the collate on the query to create a new table with that query, for example:
SELECT
*
INTO
#TempTable
FROM
View_total
WHERE
YEAR(ValidFrom) <= 2007
AND YEAR(ValidTo)>= 2007
AND Id_Product = '001'
AND ProductLine COLLATE DATABASE_DEFAULT IN (SELECT Product FROM #TempAUX)
COLLATE DATABASE_DEFAULT causes the COLLATE clause inherits the collation of the current database, eliminating the difference between the two

Resources