I hate case sensitivity in databases, but I'm developing for a client who uses it. How can I turn on this option on my SQL Server, so I can be sure I've gotten the case right in all my queries?
You don't actually need to change the collation on the entire database, if you declare it on the table or columns that need to be case-sensitive. In fact, you can actually append it to individual operations as needed.
SELECT name WHERE 'greg' = name COLLATE Latin1_GENERAL_CS_AS
I know, you said that you want this to apply throughout the database. But I mention this because in certain hosted environments, you can't control this property, which is set when the database is created.
How about:
ALTER DATABASE database_name COLLATE collation_name
See BOL for a list of collation options and pick the case-sensitive one that best fits your needs (i.e. the one your client is using).
Obviously, it's probably a good idea to make a full backup of your database before you try this. I've never personally tried to use a database with a different collation than the server's default collation, so I don't know of any "gotchas". But if you have good backups and test it in your environment before deploying it to your client, I can't imagine that there's much risk involved.
If you have a DB that has a different collation to the instance default, you can run into problems when you try and join your tables with temporary ones. Temporary tables have to collation of the instance (because they're system objects) so you need to use the COLLATE database_default clause in your joins.
select temp.A, table.B
from #TEMPORARY_TABLE temp inner join table
on temp.X COLLATE database_default = table.Y
This forces the collation of temp.X (in this example) to the collation of the current DB.
You'll have to change the database collation. You'll also need to alter the table and column level collation. I beleive you can find a script out there if you google it.
Related
I am migrating a database and etl from MySQl to SQL Server and have hit a case sensitivity issue.
In MySql the DB is setup as case sensitive because one of the applications we are loading from has codes like 'Divh' and 'divh' in the one set (its not my doing)
all is well and the select statements all over the place in etl, queries reports etc have all used whatever the author wanted regarding case - some are all UPPER some all lower most mixed.
So, in other words MYSql has case-insensitive DDL and SQL but allows case sensitive data.
It doesn't look like SQL Server can accommodate this. If I choose a CI collation all the tables and columns are insensitive along with the data (presumably).
and the converse - If its CS everything is case-sensitive.
Am I reading it right ?
If so then I either have to change the collation of every text column in the DB
OR edit each and every query.
Ironically the 1st test was to an Azure SQL Database which was set up with the same collation (SQL_Latin1_General_CP1_CS_AS)
and it doesn't care about the case of the table name in a select.
Any ideas ?
Thanks
JC
Firstly are you aware that collation settings exist at every level in SQL Server; Instance, database, table and even field level.
It sounds like you just want to enforce the case sensitive collation for the affected fields leaving the database and DDL as a whole case insensitive.
Another trick i've used in the past is to cast values to a VARBINARY data type if you want to do data comparisions between different cases, but without the need to change the collation of anything.
For example:
DECLARE #Var1 VARCHAR(5)
DECLARE #Var2 VARCHAR(5)
SET #Var1 = 'Divh'
SET #Var2 = 'divh'
--Comparison1:
IF #Var1 = #Var2
PRINT 'Same'
ELSE
PRINT 'Not the same'
--Comparison2:
IF CAST(#Var1 AS VARBINARY) = CAST(#Var2 AS VARBINARY)
PRINT 'Same'
ELSE
PRINT 'Not the same'
We just migrated some databases to a new SQL Server 2012 and got some problems with sensitivity.
We would like table & column names to be case insensitive but values should be case sensitive, so
select ... where 'a'='A'
should not return any row, but
select Column from Table
select column from table
should both work.
We tried changing the database (server default) from
Modern_Spanish_CI_AS -> 'a'='A' is true, which we don't want to be, to
Modern_Spanish_CS_AS -> the column/table names must match the defined case
Is there any way to get the desired behavior?
If you choose a case-sensitive collation you must ensure that your your queries are case-sensitive because collation applies to metadata as well as user-data .
You can get round the problem by making the database's collation case-insensitive and using the COLLATE clause when creating tables, or alternatively use a contained database.
Read more about Contained Databases and Contained Database Collations
I have an ACCESS database in which characters are Arabic but displayed like this "ÇáÓíÏ ÇáÇãíä ÇáÚÇã ááÍßæãÉ" , is there any solution to this problem please? Thanks
This is a collation problem.
ALTER DATABASE (Database name here) COLLATE Arabic_CI_AS ;
All databases have a default collation (which can be set when creating or altering a database. This collation is used for all metadata in the database, as well as the default for all string columns within the database. Users can choose a different collation for any particular column by using the COLLATE clause.
Go here, for further reading.
I'm trying to compare the schemas of two tables that exist in different databases. So far, I have this query
SELECT * FROM sys.columns WHERE object_id = OBJECT_ID('table1')
The only thing is that I don't know how to use the sys.columns to reference a database other than the one that the query is connected to. I tried this
SELECT * FROM db.sys.columns WHERE object_id = OBJECT_ID('table1')
but it didn't find anything.
I'm using SQL Server 2005
Any suggestions? thanks!
Take a look at redgate's SQL Compare.
To answer your specific question, you need to fully qualify the table reference.
SELECT * FROM db.sys.columns WHERE object_id = OBJECT_ID('db.SchemaName.table1')
Late one but hopefully useful.
Even though chama asked for SQL solutions I’d still recommend using a third party tools such as ApexSQL Diff or tools from Red Gate Joe already mentioned (I’ve used both and they worked great).
Reason is that query for comparing two tables using information schema has to be quite complex in order to catch all differences.
Note that all of the examples mentioned here only cover columns but none of the queries shown here will show the difference between nvarchar(20) and nvarchar(50) or difference in foreign keys or indexes or….
Short answer is yes – this is possible using information schema views but it can be rather complex if you want to compare every detail in those two tables.
all you need is to specify the DB name and shcema when calling OBJECT_ID function, like:
SELECT *
FROM DB_NAME.sys.columns
WHERE object_id = OBJECT_ID('DB_NAME.SHCEMA_NAME.table1')
Try the information_schema. eg:
select *
from
db1.information_schema.columns col1
join db2.information_schema.columns col2
on col1.table_catalog = col2.table_catalog
and col1.table_schema = col2.table_schema
and col1.column_name = col2.column_name
...
The information_schema simplifies sticking together the information from all the sys.columns,sys.objects etc. It exists automatically in your DB. I think its actually an ISO standard thing, so should work on various DB systems.
More information about the information_schema can be found here
Comparing whether the object or columns exists in both schemas is only a tiny bit of the solution. What if they exist in both databases but are different?
For my bsn ModuleStore project, I implemented a scripting routine which actually scripts most DB objects including table and view columns, indexes, namespaces etc. as XML using T-SQL code only. This may be a good place to start. You can find it on Google code, and the file in question (which generates the SQL query for dumping the object schema to XML) is here.
Code -
drop table #a
drop table #b
select *
into #a
from [databasename1].information_schema.columns a
--where table_name = 'aaa'
select *
into #b
from [databasename2].information_schema.columns b -- add linked server name and db as needed
--where table_name = 'bbb'
select distinct( a.table_name), b.TABLE_SCHEMA+ '.' + (b.table_name) TableName,b.TABLE_CATALOG DatabaseName
from #a a
right join #b b
on a.TABLE_NAME = b.TABLE_NAME and a.TABLE_SCHEMA = b.TABLE_SCHEMA
where a.table_name is null-- and a.table_name not like '%sync%'
Just in case you are using MS VS 2015 (Community is a free download). The SOL Server tools includes a Schema Comparison tool. "SQL Server Data Tools (SSDT) includes a Schema Compare utility that you can use to compare two database definitions".
This is a GPL Java program I wrote for comparing data in any two tables, with a common key and common columns, across any two heterogeneous databases using JDBC: https://sourceforge.net/projects/metaqa/
It intelligently forgives (numeric, string and date) data type differences by reducing them to a common format. The output is a sparse tab delimited file with .xls extension for use in a spreadsheet.
The program ingests SQL that is used to produce a source table that can be compared with the target table. The target table SQL can be generated automatically. The target table is read one row at a time and therefore should be indexed on the common key.
It detects missing rows on either side and common keyed rows with other optional column differences. Obviously the meta data can be accessed by SQL so whether your concern is with the data, or with the meta-data, it will still work.
This is very powerful in a data migration or System migration project, and also for auditing interfaces. You will be astounded at the number of errors it detects. Minimal false positives still do occur.
Informix, Oracle and SQL-Server were the first JDBC targets and you can extend that list if desired.
I am using SQL Server 2008 express edition and its collation settings are set to default.I wish to store special characeters like á ,â ,ã ,å ,ā ,ă ,ą ,ǻ in my database but it converts them into normal characters like 'a'. How can I stop SQL Server from doing so?
Make sure that your columns are using the type nvarchar(...), rather than varchar(...). The former is Unicode, the latter is ASCII.
Also, make sure that your database default collation is set to Accent Sensitive, and that your columns are stored that way. You may also want to check your instance default collation, as that affects the default collation for your system databases, particularly tempdb.
Rahul, here is a very simple query that runs perfectly on SQL 2005 and 2008:
Query
DECLARE #t1 TABLE (
Col1 nvarchar(30)
)
INSERT INTO #t1 VALUES (N'á ,â ,ã ,å ,ā ,ă ,ą ,ǻ')
SELECT * FROM #t1
Result
Col1
------------------------------
á ,â ,ã ,å ,ā ,ă ,ą ,ǻ
There is nothing special here. No collation change from default, just a simple NVARCHAR column.
You said you are "just running direct queries in the database". Can you try this query and see if you get the same results?