SQL Collation mismatching issue - sql

Have some collation(?) troubles when getting data from ADODB.RecordSet.
When selecting with SQL Management studio everything looks fine like
PriceMonitoring Справочник конкурентов2_Temp Table 6142061 dbo
Buuut, when i get data from powerdesigner's vbscript i got table names mismatching like
Table
Not in Model dbo.Ni?aai?iee eiieo?aioia2_Temp
Not in DB dbo.Справочник конкурентов2_Temp
For this moment i've already tried to specify different collations (COLLATE SQL_Latin1_General_CP1_CI_AS, Cyrillic_General_CI_AS, Ukrainian_CI_AS) in my sql script. I even changed DB collation, that doesn't help and had no effect to result. Any ideas, community?
That is a part of sql script.
SET NOCOUNT ON
USE DB_Control
SELECT ds.*, isnull(upo.Object_Name,'') as Object_Name_Updated, isnull(tuo.Object_Name,'') as Object_Name_Uncontrol
FROM
--
dbo.Design_Checksum AS ds
--
LEFT JOIN dbo.Uncontrolled_Object AS uo
ON uo.DB_Name = ds.DB_Name
AND uo.Object_Type_ID = ds.Object_Type_ID
AND uo.Schema_Name = ds.Schema_Name
AND uo.Object_Name COLLATE SQL_Latin1_General_CP1_CI_AS = ds.Object_Name COLLATE SQL_Latin1_General_CP1_CI_AS
--
LEFT JOIN dbo.Updated_Object AS upo
ON upo.DB_Name = ds.DB_Name
AND upo.Object_Type_ID = ds.Object_Type_ID
AND upo.Schema_Name = ds.Schema_Name
AND upo.Object_Name COLLATE SQL_Latin1_General_CP1_CI_AS = ds.Object_Name COLLATE SQL_Latin1_General_CP1_CI_AS
--
LEFT JOIN PD.Test_Uncontrolled_Object AS tuo
ON tuo.DB_Name = ds.DB_Name
AND tuo.Object_Type_ID = ds.Object_Type_ID
AND tuo.Schema_Name = ds.Schema_Name
AND tuo.Object_Name COLLATE SQL_Latin1_General_CP1_CI_AS = ds.Object_Name COLLATE SQL_Latin1_General_CP1_CI_AS
AND (tuo.Date_End IS NULL
OR tuo.Date_End > GETDATE())
WHERE
ds.DB_Name = 'PriceMonitoring'
AND uo.Object_Name IS NULL
ORDER BY
UPPER(REPLACE(ds.Object_Type_ID, '_', '!')),
UPPER(REPLACE(ds.Schema_Name, '_', '!')),
UPPER(REPLACE(ds.Object_Name, '_', '!'))

Related

Regular Collation issue but collate statement on join still giving same error

I have the following query:
Update
AEB
Set
[hbs_mailreturned] = 1
from
AccountExtensionBase AEB
Inner Join #IndividualsIDs I1 on
AEB.hbs_organisationid collate SQL_Latin1_General_CP1_CI_AS = I1.hbs_individualid collate SQL_Latin1_General_CP1_CI_AS
It is giving the following error message:
Cannot resolve the collation conflict between "SQL_Latin1_General_CP1_CI_AS" and "Latin1_General_CI_AI" in the equal to operation.
I don't understand this because I have specifying the collation to use on the join statement. What am I missing here?
I guess this will not create issue which you have applied on your columns,
AEB.hbs_organisationid collate SQL_Latin1_General_CP1_CI_AS = I1.hbs_individualid collate SQL_Latin1_General_CP1_CI_AS
please check for null for column values applied in join, if still not working then you can try
where fieldname COLLATE DATABASE_DEFAULT = secondfieldname COLLATE DATABASE_DEFAULT

Differentiate ø and ae

When I do an SQL ae and æ are interpreted as the same (danish collation):
select * from directories where path='test.dk\kkl$\Faelles'
Is there anyway to do a query that handles æ and ae as unique?
I used exactly #Heinzi's code here (he used the collation)
I just wanted to show how you can use it in a WHERE clause and in ORDER BY clause with a sample
At first I though you require NVARCHAR() data type but I see VARCHAR() also support Danish characters without an issue ( at least your sample )
declare #code nvarchar(100) = 'æ'
--declare #code nvarchar(100) = 'ae'
select *
from Danish
where code = #code COLLATE Danish_Greenlandic_100_CI_AI
--order by code COLLATE Danish_Greenlandic_100_CI_AI desc
So you need to set the Collation with COLLATE clause in WHERE clause or in ORDER BY for each condition or group by field,
After #Thomas' comment, I added following query.
It will produce seperate rows for 'æ' and 'ae'
SELECT
path COLLATE Danish_Greenlandic_100_CI_AI,
migrate, ismigrationroot,
COUNT(*) as CNT
FROM directories
GROUP BY
path COLLATE Danish_Greenlandic_100_CI_AI,
migrate,
ismigrationroot
HAVING
COUNT(*) > 1 and
ismigrationroot is not null

Temp Table collation conflict - Error : Cannot resolve the collation conflict between Latin1* and SQL_Latin1*

I can't update temp table. This is my query
CREATE TABLE #temp_po(IndentID INT, OIndentDetailID INT, OD1 VARCHAR(50), OD2 VARCHAR(50),
OD3 VARCHAR(50), ORD VARCHAR(50), NIndentDetailID INT, ND1 VARCHAR(50), ND2 VARCHAR(50),
ND3 VARCHAR(50), NRD VARCHAR(50), Quantity DECIMAL(15,3))
INSERT INTO #temp_po(IndentID, OIndentDetailID, OD1, OD2, OD3, ORD)
SELECT ID.IndentID, ID.IndentDetailID, ID.D1, ID.D2, ID.D3, ID.RandomDimension
FROM STR_IndentDetail ID WHERE ID.IndentID = #IndentID
UPDATE
t
SET
t.ND1 = CASE WHEN D.D1 = '' THEN NULL ELSE D.D1 END,
t.ND2 = CASE WHEN D.D2 = '' THEN NULL ELSE D.D2 END,
t.ND3 = CASE WHEN D.D3 = '' THEN NULL ELSE D.D3 END,
t.NRD = CASE WHEN D.RandomDim = '' THEN NULL ELSE D.RandomDim END,
t.Quantity = D.PurchaseQty
FROM
#temp_po t INNER JOIN #detail D ON D.IndentDetailID = t.OIndentDetailID
WHERE
t.IndentID = #IndentID
But it gives the error
Cannot resolve the collation conflict between "Latin1_General_CI_AI" and "SQL_Latin1_General_CP1_CI_AS" in the equal to operation.
How to resolve this problem?
My tempdb collation is Latin1_General_CI_AI and my actual database collation is SQL_Latin1_General_CP1_CI_AS.
This happens because the collations on #tempdb.temp_po.OD1 and STR_IndentDetail.D1 are different (and specifically, note that #tempdb is a different, system database, which is generally why it will have a default opinion for collation, unlike your own databases and tables where you may have provided more specific opinions).
Since you have control over the creation of the temp table, the easiest way to solve this appears to be to create *char columns in the temp table with the same collation as your STR_IndentDetail table:
CREATE TABLE #temp_po(
IndentID INT,
OIndentDetailID INT,
OD1 VARCHAR(50) COLLATE SQL_Latin1_General_CP1_CI_AS,
.. Same for the other *char columns
In the situation where you don't have control over the table creation, when you join the columns, another way is to add explicit COLLATE statements in the DML where errors occur, either via COLLATE SQL_Latin1_General_CP1_CI_AS or easier, using COLLATE DATABASE_DEFAULT
SELECT * FROM #temp_po t INNER JOIN STR_IndentDetail s
ON t.OD1 = s.D1 COLLATE SQL_Latin1_General_CP1_CI_AS;
OR, easier
SELECT * FROM #temp_po t INNER JOIN STR_IndentDetail s
ON t.OD1 = s.D1 COLLATE DATABASE_DEFAULT;
SqlFiddle here
Changing the server collation is not a straight forward decision, there may be other databases on the server which may get impacted. Even changing the database collation is not always advisable for an existing populated database. I think using COLLATE DATABASE_DEFAULT when creating temp table is the safest and easiest option as it does not hard code any collation in your sql. For example:
CREATE TABLE #temp_table1
(
column_1 VARCHAR(2) COLLATE database_default
)
By default temp table take the collation of server. So instead updating all stored procedure with temp table change only server collation.
Check this link for Set or Change the Server Collation
This worked for me.
We ran into the same problem right now. Instead of adding the collation to the temp table creation (or to each temp table join), we just changed the temp table creation to a table variable declaration.

SQL Server: can't collate variables in SELECT-Statement

I have 2 databases (X and Y) on my SQL Server 2008 R2. For some reason the databases and the server have different encodings (SQL_Latin1_general_CP1_CI_AS and Latin1_General_CI_AS) so I'm always facing collate problems when I use temp tables or table variables.
Selecting some info from database Y into the table variable #info
When I try to join both in this way it work really fine:
select d.data_id, i.info_id, i.info_value
from X.aaa.data d
join #info i on i.serial COLLATE DATABASE_DEFAULT =
SUBSTRING(d.serial, 17, 10) COLLATE DATABASE_DEFAULT
But the serial length can be different for different products so I want to do it with a variable:
declare #serial_length int = 10;
-- some switch case to set #serial_length to some other value
select d.data_id, i.info_id, i.info_value
from X.aaa.data d
join #info i on i.serial COLLATE DATABASE_DEFAULT =
SUBSTRING(d.serial, 17, #serial_length) COLLATE DATABASE_DEFAULT
When I try this the query will just run forever and do nothing.
Is there a workaround for this problem? Or does at least anyone know why this is happening?
UPDATE: Thanks to MitchWheat the collate isn't a problem any more Changing Database Collation and dealing with TempDB Objects
But the SELECT still doesn't work. I'm using SUBSTRING(serial, 17, #serial_length) also in another procedure but without table variables and there it works.

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