Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Case Sensitive column names in Sql Azure Database

Forever I've used a case sensitive collation in Sql Server (SQL_Latin1_General_CP1_CS_AS). I'm trying to move to Sql Azure Database and I've run into an unexpected problem. It looks like it's impossible to have case sensitive column names. Can this be true?

I create my database...

CREATE DATABASE MyDatabase
COLLATE SQL_Latin1_General_CP1_CS_AS

And I create my table...

CREATE TABLE [MyTable]
(
    [Name] NVarChar (4000) COLLATE SQL_Latin1_General_CP1_CS_AS NULL,
    [name] NVarChar (4000) COLLATE SQL_Latin1_General_CP1_CS_AS NULL                                                                                
)

And I get the error: Column names in each table must be unique. Column name 'name' in table 'MyTable' is specified more than once.

Ugh, disaster. This works perfectly in Sql Server 2012. However on Sql Azure I can't seem to make it happen. Does anyone know why this is not working in Sql Azure? Does anyone know how I can make this work in Sql Azure? Thanks.

like image 940
BowserKingKoopa Avatar asked Dec 06 '13 20:12

BowserKingKoopa


2 Answers

I think this is a bug in Windows Azure SQL!

On line documentation states that you can override the collation at the database, column or expression levels. You can not do it at the server level.

http://msdn.microsoft.com/en-us/library/windowsazure/ee336245.aspx#sscs

Lets start with something we know will work, a local install of SQL Server 2012.

-- Start at master
Use master;
Go

-- Create a new database
CREATE DATABASE Koopa
  COLLATE SQL_Latin1_General_CP1_CS_AS;

-- Use the new database
Use Koopa;
Go

-- Create a new table
CREATE TABLE [MyTable]
(
    [ColName1] NVarChar (4000) COLLATE SQL_Latin1_General_CP1_CS_AS NULL,
    [colname1] NVarChar (4000) COLLATE SQL_Latin1_General_CP1_CS_AS NULL                                                                                
);

If we try to run the create table in the MASTER database, we get your error.

Msg 2705, Level 16, State 3, Line 2

Column names in each table must be unique. Column name 'colname1' in table 'MyTable' is specified more than once.

If we run the create table in the Koopa database, it works fine. See image below. That is because MASTER is Case Insensitive CI!

enter image description here

I am going to use the Web Interface for Azure SQL database since it has nice colors (it is the web)!

Let's create a new database with the Case Sensitive collation. Wow I am getting excited since there is an option to select our collation.

enter image description here

Now that we have a new database, lets check the settings!

enter image description here

I am still happy since we see the correct collation listed for the database.

Lets log onto the database server directly and run a simple query to create the table.

I am going to try the designer first!

enter image description here

Oops, It did not work.

Lets try a simple DDL statement in a query window.

enter image description here

Now I am really disappointed. We were sold a bill of goods but Azure SQL did not deliver.

In short, the documentation says you can not set the collation at the server level.

http://technet.microsoft.com/en-us/library/ms143726.aspx

However, this Quote from BOL states we should be able to over ride it at the database level.

Server-level collations The default server collation is set during SQL Server setup, and also becomes the default collation of the system databases and all user databases. Note that Unicode-only collations cannot be selected during SQL Server setup because they are not supported as server-level collations.

enter image description here

In short, I am extremely busy with a couple speaking engagements for PASS the next 7 days. I will have to open a bug report or see if there is one already open.

Good find!!

BTW - You now need to use distinct column names.

like image 71
CRAFTY DBA Avatar answered Sep 25 '22 20:09

CRAFTY DBA


To solve your case you need to add CATALOG_COLLATION.

CREATE DATABASE MyDatabase COLLATE SQL_Latin1_General_CP1_CS_AS WITH CATALOG_COLLATION = DATABASE_DEFAULT 

Source: What will happen with CATALOG_COLLATION and Case Sensitive vs Case Insensitive

Unfortunately it looks like you can put only two values there: SQL_Latin1_General_CP1_CI_AS or DATABASE_DEFAULT

I had mirror problem. I wanted to get schema objects (table names, column names etc.) to be CI and data inside of database to be CS. - This works in Azure by default with CS COLLATE eg. SQL_Latin1_General_CP1_CS_AS set on database creation. But it does not work on local SQLEXPRESS database which is a problem to test application locally. When you create database case sensitive CS then all queries starts to be case sensitive too. This makes my hibernate stop to work. (Object does not exists etc).

To solve this I need to create database with SQL_Latin1_General_CP1_CI_AS COLLATE and define CS COLLATE for each column separately:

create table test (
 pk int PRIMARY KEY,
 data_cs varchar(123) COLLATE SQL_Latin1_General_CP1_CS_AS,
 CONSTRAINT [unique_data] UNIQUE NONCLUSTERED (data_cs)
)

insert into TEST values (1, 'ABC');
insert into tEsT values (2, 'abc');

select * from TEST where DATA_cs like 'A%'

CATALOG_COLLATION works in Azure SQL only I guess.

like image 33
tpiec Avatar answered Sep 25 '22 20:09

tpiec