Making a view case insensitive for a case sensitive table - sql

Is is possible to make a view case insensitive if the table (or view) it is looking at is case sensitive?
I have view on a database that looks at a view on another server (that I can't alter) that is case sensitive, and stored in all caps. I want my view to be case insensitive, but I can't find a way to do it. Collate only works on the select statement, because I can't alter the view to add collation. The table's properties show that it's case insensitive, but it isn't.
The results of
exec sp_help 'dbo.myView'
shows that the collation is case sensitive. Is there a way to do this?

Just add COLLATE SQL_Latin1_General_CP1_CI_AS to the columns coming from the remote table.
CREATE VIEW [dbo].[myView] (
TextColumn1,
Column2,
TextColumn3)
AS
SELECT
t.TextColumn1 COLLATE SQL_Latin1_General_CP1_CI_AS,
t.Column2,
t.TextColumn3 COLLATE SQL_Latin1_General_CP1_CI_AS
FROM
RemoteServer.dbo.REMOTE_TABLE AS t
GO
Reference:
COLLATE (Transact-SQL)

CREATE TABLE tb_CollateTest (str varchar(max))
GO
INSERT tb_CollateTest VALUES
('Unique')
,('uNiQuE')
GO
CREATE VIEW vw_CollateTest AS
SELECT
str COLLATE SQL_Latin1_General_CP1_CS_AS AS str
FROM tb_CollateTest
GROUP BY str COLLATE SQL_Latin1_General_CP1_CS_AS
GO
SELECT * FROM vw_CollateTest
str
----------
Unique
uNiQuE
(2 row(s) affected)

Related

How to remove extended ASCII chars from SQL Server

So trying to remove all the extended ascii characters and used collation SQL_Latin1_General_CP1253_CI_AI in the ddl but still getting ascii characters. Is there any suggestion ?
I have a value stored in the sql as 'àccõrd' and i want it to be stored as accord. When i try select àccõrd collate SQL_Latin1_General_CP1253_CI_AI it works but when i load it still gets loaded as àccõrd
Here are two ways to achieve what you're trying to do...
First method: define the column with a specific collation, e.g.:
create table dbo.Foo (
FooName varchar(50) collate SQL_Latin1_General_CP1253_CI_AI
);
insert dbo.Foo (FooName) values ('àccõrd');
select FooName from dbo.Foo;
Which yields:
FooName
-------
accord
Second method: collate the text when inserting it into your table:
-- Display the SQL Server instance's "default collation," configured during setup.
-- e.g.: SQL_Latin1_General_CP1_CI_AS
select serverproperty('collation') as ServerCollation;
-- Display the current database's "default collation," configured in CREATE DATABASE.
-- e.g.: SQL_Latin1_General_CP1_CI_AS
select collation_name
from sys.databases
where [name]=db_name();
create table dbo.Bar (
BarName varchar(50) --database default: collate SQL_Latin1_General_CP1_CI_AS
);
insert dbo.Bar (BarName) values ('àccõrd' collate SQL_Latin1_General_CP1253_CI_AI);
select BarName from dbo.Bar;
Which yields:
BarName
-------
accord
NOTE: These collation tricks only work with char and varchar data types.

SQL Server Collation conflict - creating a view

i am trying to create a View in a Database A, that is filled by a select from the Database B and i am having a collation conflict, to be more exactly , its between ( Latin1_General_CI_AS" and "Latin1_General_BIN ). WHere(in the code) i need to put the collate?
Best Regards.
The code is here:
CREATE VIEW [dbo].[CML_SDG_MENSAL_ESTOQUE]
AS
select
SUM(dw_fato_faturmes.val_fatur) val_fatur,
SUM(dw_fato_faturmes.val_receita) val_receita,
SUM(dw_fato_faturmes.qtd_bonif_item) qtd_bonif_item,
SUM(dw_fato_faturmes.val_bonif_fatur) val_bonif_fatur,
SUM(dw_fato_faturmes.val_bonif_receita) val_bonif_receita,
SUM(dw_fato_faturmes.val_devol_fatur) val_devol_fatur,
SUM(dw_fato_faturmes.val_devol_receita) val_devol_receita,
DW_DIM_PRODUTO.B1_CODDB B1_CODDB,
dw_fato_faturmes.cod_produto cod_produto,
SUM(dw_fato_faturmes.qtd_estoque) qtd_estoque,
SUM(dw_fato_faturmes.qtd_devol) qtd_devol,
SUM(dw_fato_faturmes.qtd_item) qtd_item,
SUM(dw_fato_faturmes.qtd_meta) qtd_meta,
SUM(dw_fato_faturmes.qtd_pedido) qtd_pedido,
SUM(dw_fato_faturmes.qtd_item)+
SUM(dw_fato_faturmes.qtd_bonif_item)+
SUM(dw_fato_faturmes.qtd_devol) venda_liquida
(SUM(dw_fato_faturmes.qtd_item)
+SUM(dw_fato_faturmes.qtd_bonif_item)
+SUM(dw_fato_faturmes.qtd_devol))
+SUM(dw_fato_faturmes.qtd_pedido) venda___pedido
FROM
logixbi.dbo.dw_fato_faturmes dw_fato_faturmes,
logixbi.dbo.DW_DIM_CLIENTE DW_DIM_CLIENTE,
DW_DIM_EMPRESA DW_DIM_EMPRESA,
logixbi.dbo.DW_DIM_MARCA DW_DIM_MARCA,
logixbi.dbo.DW_DIM_PRODUTO DW_DIM_PRODUTO,
logixbi.dbo.DW_DIM_REPRESENTANTE DW_DIM_REPRESENTANTE
where
DW_DIM_EMPRESA.SM0_FILIAL=dw_fato_faturmes.filial and
DW_DIM_MARCA.BM_GRUPO=dw_fato_faturmes.grupo and
DW_DIM_PRODUTO.B1_COD=dw_fato_faturmes.cod_produto and
DW_DIM_REPRESENTANTE.A3_COD=dw_fato_faturmes.vendedor and
DW_DIM_CLIENTE.A1_COD=dw_fato_faturmes.cliente and
DW_DIM_CLIENTE.A1_LOJA=dw_fato_faturmes.loja
group by DW_DIM_PRODUTO.B1_CODDB,dw_fato_faturmes.cod_produto
In order to find wich column has wich collation use this snippet:
SELECT name, collation_name
FROM sys.columns
WHERE OBJECT_ID IN (SELECT OBJECT_ID
FROM sys.objects
WHERE type = 'U'
AND name = 'your_table_name'
)
AND name = 'your_column_name'
Once you find the columns try this:
column_1 COLLATE your_collation = column_2 COLLATE your_collation
It is better to stick to a single collation globally. Otherwise you will have problems. Here is a snippet that will give you all the columns on your database with a COLLATION different than the one in the database
SELECT [TABLE_NAME] = OBJECT_NAME([id]),
[COLUMN_NAME] = [name],
[COLLATION_NAME] = collation
FROM syscolumns
WHERE collation <> 'your_database_collation_type'
AND collation IS NOT NULL
AND OBJECTPROPERTY([id], N'IsUserTable')=1
Where to put it depends on where the conflict is.
I'd suggest on the joins
ie
DW_DIM_EMPRESA.SM0_FILIAL COLLATE Latin1_General_CI_AS =dw_fato_faturmes.filial COLLATE Latin1_General_CI_AS
This is happening due to operation between different collation types so try this for statement for comparison.
ColumnA = ColumnB collate database_default
Try to use this in all your character matching conditions in where clause:
colnameA COLLATE Latin1_General_CI_AS = columnnameB COLLATE Latin1_General_CI_AS

How to find values in all caps in SQL Server?

How can I find column values that are in all caps? Like LastName = 'SMITH' instead of 'Smith'
Here is what I was trying...
SELECT *
FROM MyTable
WHERE FirstName = UPPER(FirstName)
You can force case sensitive collation;
select * from T
where fld = upper(fld) collate SQL_Latin1_General_CP1_CS_AS
Try
SELECT *
FROM MyTable
WHERE FirstName = UPPER(FirstName) COLLATE SQL_Latin1_General_CP1_CS_AS
This collation allows case sensitive comparisons.
If you want to change the collation of your database so you don't need to specifiy a case-sensitive collation in your queries you need to do the following (from MSDN):
1) Make sure you have all the information or scripts needed to re-create your user databases and all the objects in them.
2) Export all your data using a tool such as the bcp Utility.
3) Drop all the user databases.
4) Rebuild the master database specifying the new collation in the SQLCOLLATION property of the setup command. For example:
Setup /QUIET /ACTION=REBUILDDATABASE /INSTANCENAME=InstanceName
/SQLSYSADMINACCOUNTS=accounts /[ SAPWD= StrongPassword ]
/SQLCOLLATION=CollationName
5) Create all the databases and all the objects in them.
6) Import all your data.
You need to use a server collation which is case sensitive like so:
SELECT *
FROM MyTable
WHERE FirstName = UPPER(FirstName) Collate SQL_Latin1_General_CP1_CS_AS
Be default, SQL comparisons are case-insensitive.
Try
SELECT *
FROM MyTable
WHERE FirstName = LOWER(FirstName)
Could you try using this as your where clause?
WHERE PATINDEX(FirstName + '%',UPPER(FirstName)) = 1
Have a look here
Seems you have a few options
cast the string to VARBINARY(length)
use COLLATE to specify a case-sensitive collation
calculate the BINARY_CHECKSUM() of the strings to compare
change the table column’s COLLATION property
use computed columns (implicit calculation of VARBINARY)
Try This
SELECT *
FROM MyTable
WHERE UPPER(FirstName) COLLATE Latin1_General_CS_AS = FirstName COLLATE Latin1_General_CS_AS
You can find good example in Case Sensitive Search: Fetching lowercase or uppercase string on SQL Server
I created a simple UDF for that:
create function dbo.fnIsStringAllUppercase(#input nvarchar(max)) returns bit
as
begin
if (ISNUMERIC(#input) = 0 AND RTRIM(LTRIM(#input)) > '' AND #input = UPPER(#input COLLATE Latin1_General_CS_AS))
return 1;
return 0;
end
Then you can easily use it on any column in the WHERE clause.
To use the OP example:
SELECT *
FROM MyTable
WHERE dbo.fnIsStringAllUppercase(FirstName) = 1
Simple way to answer this question is to use collation. Let me try to explain:
SELECT *
FROM MyTable
WHERE FirstName COLLATE SQL_Latin1_General_CP1_CI_AS='SMITH’
In the above query I have used collate and didn’t use any in built sql functions like ‘UPPER’. Reason because using inbuilt functions has it’s own impact.
Please find the link to understand better:
performance impact of upper and collate

SQL Server check case-sensitivity?

How can I check to see if a database in SQL Server is case-sensitive? I have previously been running the query:
SELECT CASE WHEN 'A' = 'a' THEN 'NOT CASE SENSITIVE' ELSE 'CASE SENSITIVE' END
But I am looking for other ways as this has actually given me issues in the past.
Edit - A little more info:
An existing product has many pre-written stored procedures. In a stored procedure #test != #TEST depending on the sensitivity of the server itself. So what I'm looking for is the best way to check the server for its sensitivity.
Collation can be set at various levels:
Server
Database
Column
So you could have a Case Sensitive Column in a Case Insensitive database. I have not yet come across a situation where a business case could be made for case sensitivity of a single column of data, but I suppose there could be.
Check Server Collation
SELECT SERVERPROPERTY('COLLATION')
Check Database Collation
SELECT DATABASEPROPERTYEX('AdventureWorks', 'Collation') SQLCollation;
Check Column Collation
select table_name, column_name, collation_name
from INFORMATION_SCHEMA.COLUMNS
where table_name = #table_name
If you installed SQL Server with the default collation options, you might find that the following queries return the same results:
CREATE TABLE mytable
(
mycolumn VARCHAR(10)
)
GO
SET NOCOUNT ON
INSERT mytable VALUES('Case')
GO
SELECT mycolumn FROM mytable WHERE mycolumn='Case'
SELECT mycolumn FROM mytable WHERE mycolumn='caSE'
SELECT mycolumn FROM mytable WHERE mycolumn='case'
You can alter your query by forcing collation at the column level:
SELECT myColumn FROM myTable
WHERE myColumn COLLATE Latin1_General_CS_AS = 'caSE'
SELECT myColumn FROM myTable
WHERE myColumn COLLATE Latin1_General_CS_AS = 'case'
SELECT myColumn FROM myTable
WHERE myColumn COLLATE Latin1_General_CS_AS = 'Case'
-- if myColumn has an index, you will likely benefit by adding
-- AND myColumn = 'case'
SELECT DATABASEPROPERTYEX('<database name>', 'Collation')
As changing this setting can impact applications and SQL queries, I would isolate this test first. From SQL Server 2000, you can easily run an ALTER TABLE statement to change the sort order of a specific column, forcing it to be case sensitive. First, execute the following query to determine what you need to change it back to:
EXEC sp_help 'mytable'
The second recordset should contain the following information, in a default scenario:
Column_Name Collation
mycolumn SQL_Latin1_General_CP1_CI_AS
Whatever the 'Collation' column returns, you now know what you need to change it back to after you make the following change, which will force case sensitivity:
ALTER TABLE mytable
ALTER COLUMN mycolumn VARCHAR(10)
COLLATE Latin1_General_CS_AS
GO
SELECT mycolumn FROM mytable WHERE mycolumn='Case'
SELECT mycolumn FROM mytable WHERE mycolumn='caSE'
SELECT mycolumn FROM mytable WHERE mycolumn='case'
If this screws things up, you can change it back, simply by issuing a new ALTER TABLE statement (be sure to replace my COLLATE identifier with the one you found previously):
ALTER TABLE mytable
ALTER COLUMN mycolumn VARCHAR(10)
COLLATE SQL_Latin1_General_CP1_CI_AS
If you are stuck with SQL Server 7.0, you can try this workaround, which might be a little more of a performance hit (you should only get a result for the FIRST match):
SELECT mycolumn FROM mytable WHERE
mycolumn = 'case' AND
CAST(mycolumn AS VARBINARY(10)) = CAST('Case' AS VARBINARY(10))
SELECT mycolumn FROM mytable WHERE
mycolumn = 'case' AND
CAST(mycolumn AS VARBINARY(10)) = CAST('caSE' AS VARBINARY(10))
SELECT mycolumn FROM mytable WHERE
mycolumn = 'case' AND
CAST(mycolumn AS VARBINARY(10)) = CAST('case' AS VARBINARY(10))
-- if myColumn has an index, you will likely benefit by adding
-- AND myColumn = 'case'
SQL server determines case sensitivity by COLLATION.
COLLATION can be set at various levels.
Server-level
Database-level
Column-level
Expression-level
Here is the MSDN reference.
One can check the COLLATION at each level as mentioned in Raj More's answer.
Check Server Collation
SELECT SERVERPROPERTY('COLLATION')
Check Database Collation
SELECT DATABASEPROPERTYEX('AdventureWorks', 'Collation') SQLCollation;
Check Column Collation
select table_name, column_name, collation_name
from INFORMATION_SCHEMA.COLUMNS
where table_name = #table_name
Check Expression Collation
For expression level COLLATION you need to look at the expression. :)
It would be generally at the end of the expression as in below example.
SELECT name FROM customer ORDER BY name COLLATE Latin1_General_CS_AI;
Collation Description
For getting description of each COLLATION value try this.
SELECT * FROM fn_helpcollations()
And you should see something like this.
You can always put a WHERE clause to filter and see description only for your COLLATION.
You can find a list of collations here.
You're interested in the collation. You could build something based on this snippet:
SELECT DATABASEPROPERTYEX('master', 'Collation');
Update
Based on your edit — If #test and #TEST can ever refer to two different variables, it's not SQL Server. If you see problems where the same variable is not equal to itself, check if that variable is NULL, because NULL = NULL returns `false.
The best way to work with already created tables is that,
Go to Sql Server Query Editor
Type: sp_help <tablename>
This will show table's structure , see the details for the desired field under COLLATE column.
then type in the query like :
SELECT myColumn FROM myTable
WHERE myColumn COLLATE SQL_Latin1_General_CP1_CI_AS = 'Case'
It could be different character schema <SQL_Latin1_General_CP1_CI_AS>, so better to find out the exact schema that has been used against that column.
How can I check to see if a database in SQL Server is case-sensitive?
You can use below query that returns your informed database is case sensitive or not or is in binary sort(with null result):
;WITH collations AS (
SELECT
name,
CASE
WHEN description like '%case-insensitive%' THEN 0
WHEN description like '%case-sensitive%' THEN 1
END isCaseSensitive
FROM
sys.fn_helpcollations()
)
SELECT *
FROM collations
WHERE name = CONVERT(varchar, DATABASEPROPERTYEX('yourDatabaseName','collation'));
For more read this MSDN information ;).
SQL Server is not case sensitive. SELECT * FROM SomeTable is the same as SeLeCT * frOM soMetaBLe.

SQL query to make all data in a column UPPER CASE?

I need a SQL query to make all data in a column UPPER CASE?
Any ideas?
Permanent:
UPDATE
MyTable
SET
MyColumn = UPPER(MyColumn)
Temporary:
SELECT
UPPER(MyColumn) AS MyColumn
FROM
MyTable
If you want to only update on rows that are not currently uppercase (instead of all rows), you'd need to identify the difference using COLLATE like this:
UPDATE MyTable
SET MyColumn = UPPER(MyColumn)
WHERE MyColumn != UPPER(MyColumn) COLLATE Latin1_General_CS_AS
A Bit About Collation
Cases sensitivity is based on your collation settings, and is typically case insensitive by default.
Collation can be set at the Server, Database, Column, or Query Level:
-- Server
SELECT SERVERPROPERTY('COLLATION')
-- Database
SELECT name, collation_name FROM sys.databases
-- Column
SELECT COLUMN_NAME, COLLATION_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE CHARACTER_SET_NAME IS NOT NULL
Collation Names specify how a string should be encoded and read, for example:
Latin1_General_CI_AS → Case Insensitive
Latin1_General_CS_AS → Case Sensitive