Collation conflict SQL Server 2008 - sql-server

I've been going around this but I haven't found a solution for my problem. My sql query is:
SELECT
dbo.Country.CtyRecID, dbo.Country.CtyShort, dbo.Notification.NotRecID,
dbo.Notification.NotName, dbo.TemporalSuspension.TCtsCode,
dbo.TemporalSuspension.TCtsCodeRecID,
dbo.TaxPhylum.PhyName AS Taxon, dbo.TemporalSuspension.TCtsNotes,
dbo.TemporalSuspension.TCtsRecID,
dbo.TemporalSuspension.TCtsKgmRecID,
CASE dbo.TemporalSuspension.TCtsKgmRecID WHEN 1 THEN 'Animals'
WHEN 2 THEN 'Plants' ELSE 'All' END AS Kingdom
FROM
dbo.TemporalSuspension
INNER JOIN dbo.Notification
ON dbo.TemporalSuspension.TCtsStartNotRecID = dbo.Notification.NotRecID
INNER JOIN dbo.Country
ON dbo.TemporalSuspension.TCtsCtyRecID = dbo.Country.CtyRecID
INNER JOIN dbo.TaxPhylum
ON dbo.TemporalSuspension.TCtsCodeRecID = dbo.TaxPhylum.PhyRecID
AND dbo.TemporalSuspension.TCtsCode LIKE 'PHY'
UNION ALL
SELECT
dbo.Country.CtyRecID, dbo.Country.CtyShort, dbo.Notification.NotRecID,
dbo.Notification.NotName, dbo.TemporalSuspension.TCtsCode,
dbo.TemporalSuspension.TCtsCodeRecID,
dbo.TaxClass.ClaName AS Taxon, dbo.TemporalSuspension.TCtsNotes,
dbo.TemporalSuspension.TCtsRecID,
dbo.TemporalSuspension.TCtsKgmRecID,
CASE dbo.TemporalSuspension.TCtsKgmRecID WHEN 1 THEN 'Animals'
WHEN 2 THEN 'Plants' ELSE 'All' END AS Kingdom
FROM
dbo.TemporalSuspension
INNER JOIN dbo.Notification
ON dbo.TemporalSuspension.TCtsStartNotRecID = dbo.Notification.NotRecID
INNER JOIN dbo.Country
ON dbo.TemporalSuspension.TCtsCtyRecID = dbo.Country.CtyRecID
INNER JOIN dbo.TaxClass
ON dbo.TemporalSuspension.TCtsCodeRecID = dbo.TaxClass.ClaRecID
AND dbo.TemporalSuspension.TCtsCode LIKE 'CLA'
But I don't understand why it doesn't work, I keep getting this error :
Cannot resolve collation conflict for column 7 in SELECT statement.
What's wrong? I've used this other times and I never got this problem. According to the error the dbo.TaxPhylum.PhyName AS Taxon, and dbo.TaxClass.ClaName AS Taxon, is the thing giving the problem, but I don't really understand why, both columns have the same type and everything.
EDIT: This is the result obtained with the query, how do I get around this?
Column Name Table Name collation_name
PhyName vDecisionsExpanded Latin1_General_CI_AS
ClaName vDecisionsExpanded SQL_Latin1_General_CP1_CI_AS
thanks

Try this query in your database:
SELECT
col.name 'Column Name',
OBJECT_NAME(object_id) 'Table Name',
col.collation_name
FROM sys.columns col
WHERE col.system_type_id IN (35, 99, 167, 175, 231, 239) -- TEXT, NTEXT, VARCHAR etc.
It will show you all string-related columns in your database, and their collation.
The error message says that column 7 is the culprit - that would be dbo.TaxPhylum.PhyName - so also check the TaxPhylum database. Is the collation in that database different from your normal database??
UPDATE:
if you have a collation conflict, you can do two things:
1) if it's only a single or a few columns in a SELECT, just add the COLLATE ..... modifier to them:
SELECT
.....
dbo.TaxPhylum.PhyName COLLATE SQL_Latin1_General_CP1_CI_AS AS Taxon,
.....
2) if it's a lot of columns, you might want to consider to modify the COLLATION on those columns / tables or in that database all together
How to change database or server collation

Different server/database combination? At the risk of asking the obvious, I assume that you have verified your columns collation sequences?

Related

SQL Server unique column ID's

I am working on an application that we will be using to maintain our database dictionary (description of each column in each table) and would like to build a "Refresh" function that can go to the database and get the updated column list/names.
What I'm having issues with is when a column is renamed/moved, I would like to track if there is way to update the database with the new details. I tried using the Column_ID from syscolumns, but this changes when the column is moved so seems to be an arbitrary number.
Is there any unique ID that SQL Server generates for a column that doesn't change?
My alternative is to add the new column and mark the old one as removed.
Thanks
Why don't you store the description in the column's description property. Then when the column is updated the developer would be responsible for updating this.
I wrote a web font-end to this over 10 years ago.... I could send you the code if you want? Looked like:
You can try this... its a composite of two queries:
This will get you the list of coumns inside a table:
SELECT c.object_id, OBJECT_NAME(c.object_id) AS OBJECT_NAME
,c.NAME AS COLUMN_NAME
,t.NAME AS DATA_TYPE
,c.max_length AS MAX_LENGTH
FROM sys.all_columns c
INNER JOIN sys.types t ON t.system_type_id = c.system_type_id
WHERE object_name(c.object_id) = 'TableName'
You can generate a HashCode of the column name and combine it with object_id... which should be unique unless the column name changed
Hope this will help.
I would add a new column and mark the old one as removed.
[edit]
I thought that what SQL server deleted the table and create it in the first place, and after your question I went to investigate:
If you mark the option of "Prevent saving changes that require table re creation" (in Options -> Designers -> Table and database designers) and then create the following table:
CREATE TABLE [dbo].[testTbl](
[colA] [nchar](10) NULL,
[colB] [smallint] NOT NULL
) ON [PRIMARY]
and even insert some values:
INSERT INTO dbo.testTbl
VALUES ('text1', 12)
,('text2', 22)
,('text3', 32)
,('text4', 42)
,('text5', 52)
And then run the code from above you will get:
SELECT c.object_id, OBJECT_NAME(c.object_id) AS OBJECT_NAME
,c.NAME AS COLUMN_NAME
,t.NAME AS DATA_TYPE
,c.max_length AS MAX_LENGTH
FROM sys.all_columns c
INNER JOIN sys.types t ON t.system_type_id = c.system_type_id
WHERE object_name(c.object_id) = 'testTbl'
You will get the following values:
If you try to do now the following changes (in the table designer)you will find out that all require drop and re create from the database:
Change a NULLABLE column to non-nullable
change non-nullable column to a nullable
(which is to be expected; those changes require the columns to move around the page)
change the datatype of a column (nchar(10) to more or less, smallint to tinyint or int)
but if you want to change the column from B to C, SQL can manage it, and the results would be:
The object id refers to the table id, and therefore the table stayed with the same object id.

MSSQL: alter column not null, in general

In Microsoft SQL Server 2008 R2, I would like to change a nullable column to not null. Obviously, I could do this by restating the datatype, as
alter table t alter column c int not null
if the column t.c is of int datatype, for example. But what about in general, without restating the existing data type? I'm looking for some equivalent of
alter table t alter column c not null
where the existing datatype is kept in place, and only the nullability is turned off.
Background
I have done an audit of my database and found many cases where a column is specified as nullable but no null values occur in practice. I'd like to tighten up the schema to forbid null values in these columns. Manually writing the DDL to 'alter column' for each one is error-prone because I might get the datatype wrong. I could automatically generate the code by using a schema-dumper program which outputs the existing datatype of each column, but that too has risks, if the dumper program is not aware of the latest datatypes and outputs something else (as an example, suppose it doesn't know about datetime2 and writes out datetime instead).
The SQL server already knows what the column type is, so surely there is a way to tell it to keep that and just turn off the nullability.
If there's really no way to do it except by finding the existing datatype to put it into the DDL, perhaps you could recommend a suitable tool to use? I know about dbschema.pl from Sybase days but there might be something more modern, or some well-known fragment of SQL that prints out the necessary statements from the schema views.
Two approaches:
1) Expand on this answer to include consideration for max_length,precision,scale, and collation_name. If you have multiple schemas, you will need to accommodate that too.
SELECT
'ALTER TABLE '
+QUOTENAME(aud.[table_name])
+' ALTER COLUMN '
+QUOTENAME(aud.[column_name])
+TYPE_NAME([system_type_id])
+' NOT NULL;'
FROM MyColumnAuditList aud
INNER JOIN sys.columns col ON (
col.[object_id] = OBJECT_ID(aud.[table_name]) AND
col.[name] = aud.[column_name]
)
2) In SSMS, right-click the Database and select 'Script Database As'. Use your text parsing tools of choice to extract the column definitions from the result.
The 'two approaches' answer suggested by Anon is helpful. The website's comment box doesn't allow enough text so I will post my final answer here.
The linked answer has special provision for user data types, which my database doesn't have, so I am using the type_name builtin instead. This query tries to reverse-engineer the type for each column:
select t.name,
c.name,
case
when type_name(c.system_type_id) in (
'int', 'real', 'float', 'date', 'time', 'datetime', 'datetime2',
'tinyint', 'smallint', 'smalldatetime', 'bit', 'bigint', 'timestamp',
'image'
) then type_name(c.system_type_id)
else type_name(c.system_type_id) + '('
+ case
when precision = 0 then convert(varchar(10), c.max_length)
else convert(varchar(10), precision) + ', ' + convert(varchar(10), scale)
end
+ ')'
end as ty
from sys.tables t
join sys.columns c
on t.object_id = c.object_id
where c.is_nullable = 1
and c.is_computed = 0
and t.schema_id = 1
order by t.name,
c.name
Then you can take each row from this query and do a check that no nulls exist before running 'alter table'. I am doing something like the following:
select case when
exists (select 0 from TABLE)
and not exists (select 0 from TABLE tablesample (1000 rows) where COLUMN is null)
then 1 else 0 end
for each TABLE, COLUMN returned by the first query. If the second query returns 1 then you can probably make the 'alter table' change. I use tablesample above to stop this being too heavy on the database, since I plan to run the check regularly; if the size of the table as returned by sp_spaceused is less than 100 kilobytes then I omit the tablesample clause.
Or, if you feel brave you could just run all the 'alter table' statements and let them fail if the column does contain nulls.
Oddly, I don't have permissions on the database to right-click in Management Studio and 'script database as', although I can do it for individual objects.

Collation conflict with temp table

The collation of tempdb is Latin1_General_100_CI_AI. The collation of the database is also Latin1_General_100_CI_AI. Yet the following SQL statement:
SELECT *
FROM ##CitiesMapping AS cm
INNER JOIN Cities ON cm.CityName=Cities.Name
returns:
Cannot resolve the collation conflict between "SQL_Latin1_General_CP1_CI_AS" and "Latin1_General_100_CI_AI" in the equal to operation.
The server default collation is also Latin1_General_100_CI_AI
It is possible that the collation is set differently for a single column. The query from Stuart will show you that. If they are different collations you can specify the collation being used on either side of the comparison like this:
SELECT *
FROM ##CitiesMapping AS cm
INNER JOIN Cities
ON cm.CityName COLLATE DATABASE_DEFAULT = Cities.Name COLLATE DATABASE_DEFAULT;
I hope this helps you out.
Check the tables involved as well:
SELECT name, collation_name, OBJECT_NAME(object_id)
FROM sys.columns
WHERE OBJECT_NAME(object_id) IN ('Cities')

Unable to Increase Column size

I need increase column size of the table , i am using below query to increase the size but i am getting below error
Alter Table Tabl1 Alter Column Col1 VarChar(6) Not NULL
Msg 5074, Level 16, State 1, Line 1
The object 'Tabl1' is dependent on column 'Col1'.
Msg 5074, Level 16, State 1, Line 1
The statistics '_WA_Sys_Col1_5070F446' is dependent on column 'Col1'.
Msg 4922, Level 16, State 9, Line 1
ALTER TABLE ALTER COLUMN Col1 failed because one
or more objects access this column.
Because of same table as a dependency on the column
need help on this
SQL Server automatically adds statistics to a table over time to use when it parses a query and builds a query plan. You have to drop the statistic to change the column. For instance:
drop statistics [dbo].[Tabl1].[_WA_Sys_Col1_5070F446]
However, you should use SSMS to view the columns that are in the _WA_Sys_Col1_5070F446 statistics before you drop it so that you can recreate it. Something like this:
create statistics [_WA_Sys_Col1_5070F446] on [dbo].[Tabl1]([Col1])
But there may be more columns..., so be sure to find out which need to be included before you drop it.
You can run this SQL to find most of the dependencies, it doesn't report the statistics dependencies, but it catches most of the others:
SELECT OBJECT_NAME(d.object_id) AS SP_Or_Function, OBJECT_NAME(d.referenced_major_id) AS TableReferenced
FROM sys.sql_dependencies AS d INNER JOIN
sys.all_sql_modules AS m ON m.object_id = d.object_id
where OBJECT_ID(N'Tabl1') = d.referenced_major_id
GROUP BY OBJECT_NAME(d.object_id), OBJECT_NAME(d.referenced_major_id)
ORDER BY SP_Or_Function, TableReferenced
You can find all statistics used by a given table with this query:
SELECT DISTINCT
OBJECT_NAME(s.[object_id]) AS TableName,
c.name AS ColumnName,
s.name AS StatName,
s.auto_created,
s.user_created,
s.no_recompute,
s.[object_id],
s.stats_id,
sc.stats_column_id,
sc.column_id,
STATS_DATE(s.[object_id], s.stats_id) AS LastUpdated
FROM sys.stats s JOIN sys.stats_columns sc ON sc.[object_id] = s.[object_id] AND sc.stats_id = s.stats_id
JOIN sys.columns c ON c.[object_id] = sc.[object_id] AND c.column_id = sc.column_id
JOIN sys.partitions par ON par.[object_id] = s.[object_id]
JOIN sys.objects obj ON par.[object_id] = obj.[object_id]
WHERE OBJECTPROPERTY(s.OBJECT_ID,'IsUserTable') = 1
AND (s.auto_created = 1 OR s.user_created = 1)
AND object_id(N'Tabl1') = s.[object_id]
Thanks to SQLAuthority for the last two SQL queries:
SQL SERVER – Get the List of Object Dependencies – sp_depends and information_schema.routines and sys.dm_sql_referencing_entities (Gabriel's post)
SQL SERVER – Find Details for Statistics of Whole Database – DMV – T-SQL Script
Here is quote from SQL Server 2000 help:
ALTER COLUMN
The altered column cannot be:
.....
Used in an index, unless the column is a varchar, nvarchar, or varbinary data type, the data type is not changed, and the new size is
equal to or larger than the old size.
Used in statistics generated by the CREATE STATISTICS statement. First remove the statistics using the DROP STATISTICS statement.
Statistics automatically generated by the query optimizer are
automatically dropped by ALTER COLUMN. .....

Sql Server - Using Collation

I am using below query in which I need to specify collation hint to avoid collation issues across databases as this query uses tables from 2 databases.
Msg 468, Level 16, State 9, Line 12 Cannot resolve the collation
conflict between "Latin1_General_CS_AI" and "Latin1_General_CS_AS" in
the equal to operation.
Currently I am getting above error for collation conflicts when I run some of the queries which uses different databases with different collations:
Delete from table1 where oldcolumn in
(
select newcolumn from Database2.dbo.table2
where invoiceid = #invno
and complete = 0
)
I changed the query to include collation hint as below:
Delete from table1 where oldcolumn COLLATE SQL_Latin1_General_CP1_CS_AS in
(
select newcolumn from Database2.dbo.table2
where invoiceid = #invno
and complete = 0
)
Will above query solve the problem of collation?
Is it same to specify collate hint on left or right of operator (e.g. "=" operator)?
Can query like invoiceid = #invno ever generate runtime collation conflit error?
Note: I am asking this question as I do not have access to any of the above 2 databases and the script will be run on actual databases.
Use Below Query :
DELETE FROM Table1
WHERE Table1.ID IN (
SELECT Table1.ID
FROM Table1
INNER JOIN Database2.dbo.Table2 Table2 ON Table2.NewColumn = Table1.OldColumn COLLATE SQL_Latin1_General_CP1_CS_AS
WHERE Table2.invoiceid = #invno
AND Table2.complete = 0
)

Resources