I have the following code
SELECT tA.FieldName As [Field Name],
COALESCE(tO_A.[desc], tO_B.[desc], tO_C.Name, tA.OldVAlue) AS [Old Value],
COALESCE(tN_A.[desc], tN_B.[desc], tN_C.Name, tA.NewValue) AS [New Value],
U.UserName AS [User Name],
CONVERT(varchar, tA.ChangeDate) AS [Change Date]
FROM D tA
JOIN
[DRTS].[dbo].[User] U
ON tA.UserID = U.UserID
LEFT JOIN
A tO_A
on tA.FieldName = 'AID'
AND tA.oldValue = CONVERT(VARCHAR, tO_A.ID)
LEFT JOIN
A tN_A
on tA.FieldName = 'AID'
AND tA.newValue = CONVERT(VARCHAR, tN_A.ID)
LEFT JOIN
B tO_B
on tA.FieldName = 'BID'
AND tA.oldValue = CONVERT(VARCHAR, tO_B.ID)
LEFT JOIN
B tN_B
on tA.FieldName = 'BID'
AND tA.newValue = CONVERT(VARCHAR, tN_B.ID)
LEFT JOIN
C tO_C
on tA.FieldName = 'CID'
AND tA.oldValue = tO_C.Name
LEFT JOIN
C tN_C
on tA.FieldName = 'CID'
AND tA.newValue = tN_C.Name
WHERE U.Fullname = #SearchTerm
ORDER BY tA.ChangeDate
When running the code I am getting the error pasted in the title after adding the two joins for table C. I think this may have something to do with the fact I'm using SQL Server 2008 and have restored a copy of this db on to my machine which is 2005.
I do the following:
...WHERE
fieldname COLLATE DATABASE_DEFAULT = otherfieldname COLLATE DATABASE_DEFAULT
Works every time. :)
You have a mismatch of two different collations in your table. You can check what collations each column in your table(s) has by using this query:
SELECT
col.name, col.collation_name
FROM
sys.columns col
WHERE
object_id = OBJECT_ID('YourTableName')
Collations are needed and used when ordering and comparing strings. It's generally a good idea to have a single, unique collation used throughout your database - don't use different collations within a single table or database - you're only asking for trouble....
Once you've settled for one single collation, you can change those tables / columns that don't match yet using this command:
ALTER TABLE YourTableName
ALTER COLUMN OffendingColumn
VARCHAR(100) COLLATE Latin1_General_CI_AS NOT NULL
To find the fulltext indices in your database, use this query here:
SELECT
fti.object_Id,
OBJECT_NAME(fti.object_id) 'Fulltext index',
fti.is_enabled,
i.name 'Index name',
OBJECT_NAME(i.object_id) 'Table name'
FROM
sys.fulltext_indexes fti
INNER JOIN
sys.indexes i ON fti.unique_index_id = i.index_id
You can then drop the fulltext index using:
DROP FULLTEXT INDEX ON (tablename)
Use the collate clause in your query:
LEFT JOIN C tO_C on tA.FieldName = 'CID' AND tA.oldValue COLLATE Latin1_General_CI_AS = tO_C.Name
I may not have the syntax exactly right (check BOL), but you can do this to change the collation on-the-fly for the query - you may need to add the clause for each join.
edit: I realized this was not quite right - the collate clause goes after the field you need to change - in this example I changed the collation on the tA.oldValue field.
Identify the fields for which it is throwing this error and add following to them:
COLLATE DATABASE_DEFAULT
There are two tables joined on Code field:
...
and table1.Code = table2.Code
...
Update your query to:
...
and table1.Code COLLATE DATABASE_DEFAULT = table2.Code COLLATE DATABASE_DEFAULT
...
This can easily happen when you have 2 different databases and specially 2 different databases from 2 different servers. Best option is to change it to a common collection and do the join or comparison.
SELECT
*
FROM sd
INNER JOIN pd ON sd.SCaseflowID COLLATE Latin1_General_CS_AS = pd.PDebt_code COLLATE Latin1_General_CS_AS
#Valkyrie awesome answer. Thought I put in here a case when performing the same with a subquery insides a stored procedure, as I wondered if your answer works in this case, and it did awesome.
...WHERE fieldname COLLATE DATABASE_DEFAULT in (
SELECT DISTINCT otherfieldname COLLATE DATABASE_DEFAULT
FROM ...
WHERE ...
)
In the where criteria add collate SQL_Latin1_General_CP1_CI_AS
This works for me.
WHERE U.Fullname = #SearchTerm collate SQL_Latin1_General_CP1_CI_AS
To resolve this problem in the query without changing either database, you can cast the expressions on other side of the "=" sign with
COLLATE SQL_Latin1_General_CP1_CI_AS
as suggested here.
The root cause is that the sql server database you took the schema from has a collation that differs from your local installation. If you don't want to worry about collation re install SQL Server locally using the same collation as the SQL Server 2008 database.
error (Cannot resolve the collation conflict between .... ) usually occurs while comparing data from multiple databases.
since you cannot change the collation of databases now, use COLLATE DATABASE_DEFAULT.
----------
AND db1.tbl1.fiel1 COLLATE DATABASE_DEFAULT =db2.tbl2.field2 COLLATE DATABASE_DEFAULT
I have had something like this before, and what we found was that the collation between 2 tables were different.
Check that these are the same.
Thanks to marc_s's answer I solved my original problem - inspired to take it a step further and post one approach to transforming a whole table at a time - tsql script to generate the alter column statements:
DECLARE #tableName VARCHAR(MAX)
SET #tableName = 'affiliate'
--EXEC sp_columns #tableName
SELECT 'Alter table ' + #tableName + ' alter column ' + col.name
+ CASE ( col.user_type_id )
WHEN 231
THEN ' nvarchar(' + CAST(col.max_length / 2 AS VARCHAR) + ') '
END + 'collate Latin1_General_CI_AS ' + CASE ( col.is_nullable )
WHEN 0 THEN ' not null'
WHEN 1 THEN ' null'
END
FROM sys.columns col
WHERE object_id = OBJECT_ID(#tableName)
gets:
ALTER TABLE Affiliate ALTER COLUMN myTable NVARCHAR(4000) COLLATE Latin1_General_CI_AS NOT NULL
I'll admit to being puzzled by the need to col.max_length / 2 -
Check the level of collation that is mismatched (server, database,table,column,character).
If it is the server, these steps helped me once:
Stop the server
Find your sqlservr.exe tool
Run this command:
sqlservr -m -T4022 -T3659 -s"name_of_insance"
-q "name_of_collation"
Start your sql server:
net start name_of_instance
Check the collation of your server again.
Here is more info:
https://www.mssqltips.com/sqlservertip/3519/changing-sql-server-collation-after-installation/
I have used the content from this site to create the following script which changes collation of all columns in all tables:
CREATE PROCEDURE [dbo].[sz_pipeline001_collation]
-- Add the parameters for the stored procedure here
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
SELECT 'ALTER TABLE [' + SYSOBJECTS.Name + '] ALTER COLUMN [' + SYSCOLUMNS.Name + '] ' +
SYSTYPES.name +
CASE systypes.NAME
WHEN 'text' THEN ' '
ELSE
'(' + RTRIM(CASE SYSCOLUMNS.length
WHEN -1 THEN 'MAX'
ELSE CONVERT(CHAR,SYSCOLUMNS.length)
END) + ') '
END
+ ' ' + ' COLLATE Latin1_General_CI_AS ' + CASE ISNULLABLE WHEN 0 THEN 'NOT NULL' ELSE 'NULL' END
FROM SYSCOLUMNS , SYSOBJECTS , SYSTYPES
WHERE SYSCOLUMNS.ID = SYSOBJECTS.ID
AND SYSOBJECTS.TYPE = 'U'
AND SYSTYPES.Xtype = SYSCOLUMNS.xtype
AND SYSCOLUMNS.COLLATION IS NOT NULL
AND NOT ( sysobjects.NAME LIKE 'sys%' )
AND NOT ( SYSTYPES.name LIKE 'sys%' )
END
If this occurs across the whole of your DB then it's better to change your DB collation like so:
USE master;
GO
ALTER DATABASE MyOptionsTest
COLLATE << INSERT COLATION REQUIRED >> ;
GO
--Verify the collation setting.
SELECT name, collation_name
FROM sys.databases
WHERE name = N'<< INSERT DATABASE NAME >>';
GO
Reference here
For those who have a CREATE DATABASE script (as was my case) for the database that is causing this issue you can use the following CREATE script to match the collation:
-- Create Case Sensitive Database
CREATE DATABASE CaseSensitiveDatabase
COLLATE SQL_Latin1_General_CP1_CS_AS -- or any collation you require
GO
USE CaseSensitiveDatabase
GO
SELECT *
FROM sys.types
GO
--rest of your script here
or
-- Create Case In-Sensitive Database
CREATE DATABASE CaseInSensitiveDatabase
COLLATE SQL_Latin1_General_CP1_CI_AS -- or any collation you require
GO
USE CaseInSensitiveDatabase
GO
SELECT *
FROM sys.types
GO
--rest of your script here
This applies the desired collation to all the tables, which was just what I needed. It is ideal to try and keep the collation the same for all databases on a server.
Hope this helps.
More info on the following link: SQL SERVER – Creating Database with Different Collation on Server
You could easily do this by using 4 easy steps
backup your database, just incase
change database collation: right click database, select properties, go to the options and change the collation to the required collation.
Generate a script to Drop and Recreate all your database objects: right click your database, select tasks, select generate script... ( make sure you select Drop & Create on the Advanced options of the Wizard, Also select Schema & Data )
Run the Script Generated above
INSERT INTO eSSLSmartOfficeSource2.[dbo].DeviceLogs (DeviceId,UserId,LogDate,UpdateFlag)
SELECT DL1.DeviceId ,DL1.UserId COLLATE DATABASE_DEFAULT,DL1.LogDate
,0 FROM eSSLSmartOffice.[dbo].DeviceLogs DL1
WHERE NOT EXISTS
(SELECT DL2.DeviceId ,DL2.UserId COLLATE DATABASE_DEFAULT
,DL2.LogDate ,DL2.UpdateFlag
FROM eSSLSmartOfficeSource2.[dbo].DeviceLogs DL2
WHERE DL1.DeviceId =DL2.DeviceId
and DL1.UserId collate Latin1_General_CS_AS=DL2.UserId collate Latin1_General_CS_AS
and DL1.LogDate =DL2.LogDate )
Added code to #JustSteve's answer to deal with varchar and varchar(MAX) columns:
DECLARE #tableName VARCHAR(MAX)
SET #tableName = 'first_notes'
--EXEC sp_columns #tableName
SELECT 'Alter table ' + #tableName + ' alter column ' + col.name
+ CASE ( col.user_type_id )
WHEN 231
THEN ' nvarchar(' + CAST(col.max_length / 2 AS VARCHAR) + ') '
WHEN 167
THEN ' varchar(' + CASE col.max_length
WHEN -1
THEN 'MAX'
ELSE
CAST(col.max_length AS VARCHAR)
end
+ ') '
END + 'collate Latin1_General_CI_AS ' + CASE ( col.is_nullable )
WHEN 0 THEN ' not null'
WHEN 1 THEN ' null'
END
FROM sys.columns col
WHERE object_id = OBJECT_ID(#tableName)
I had a similar error (Cannot resolve the collation conflict between "SQL_Latin1_General_CP1_CI_AS" and "SQL_Latin1_General_CP1250_CI_AS" in the INTERSECT operation), when I used old jdbc driver.
I resolved this by downloading new driver from Microsoft or open-source project jTDS.
here is what we did, in our situation we need an ad hoc query to be executed using a date restriction on demand, and the query is defined in a table.
Our new query needs to match data between different databases and include data from both of them.
It seems that the COLLATION is different between the db that imports data from the iSeries/AS400 system, and our reporting database - this could be because of the specific data types (such as Greek accents on names and so on).
So we used the below join clause:
...LEFT Outer join ImportDB..C4CTP C4 on C4.C4CTP COLLATE Latin1_General_CS_AS=CUS_Type COLLATE Latin1_General_CS_AS
You may not have any collation issues in your database whatsoever, but if you restored a copy of your database from a backup on a server with a different collation than the origin, and your code is creating temporary tables, those temporary tables would inherit collation from the server and there would be conflicts with your database.
ALTER DATABASE test2 --put your database name here
COLLATE Latin1_General_CS_AS --replace with the collation you need
I had a similar requirement; documenting my approach here for anyone with a similar scenario...
Scenario
I have a database from a clean install with the correct collations.
I have another database which has the wrong collations.
I need to update the latter to use the collations defined on the former.
Solution
Use SQL Server Schema Comparison (from SQL Server Data Tools / Visual Studio) to compare source (clean install) with destination (the db with invalid collation).
In my case I compared the two DBs directly; though you could work via a project to allow you to manually tweak pieces in between...
Run Visual Studio
Create a new SQL Server Data Project
Click Tools, SQL Server, New Schema Comparison
Select the source database
Select the target database
Click options (⚙)
Under Object Types select only those types you're interested in (for me it was only Views and Tables)
Under General select:
Block on possible data loss
Disable & reenable DDL triggers
Ignore cryptographic provider file path
Ignore File & Log File Path
Ignore file size
Ignore filegroup placement
Ignore full text catalog file path
Ignore keyword casing
Ignore login SIDs
Ignore quoted identifiers
Ignore route lifetime
Ignore semicolon between statements
Ignore whitespace
Script refresh module
Script validation for new constraints
Verify collation compatibility
Verify deployment
Click Compare
Uncheck any objects flagged for deletion (NB: those may still have collation issues; but since they're not defined in our source/template db we don't know; either way, we don't want to lose things if we're only targeting collation changes). You can unchceck all at once by right clicking on the DELETE folder and selecting EXCLUDE.
Likewise exclude for any CREATE objects (here since they don't exist in the target they can't have the wrong collation there; whether they should exist is a question for another topic).
Click on each object under CHANGE to see the script for that object. Use the diff to ensure that we're only changing the collation (anything other differences manually detected you'll likely want to exclude / handle those objects manually).
Click Update to push changes
This does still involve some manual effort (e.g. checking that you're only impacting the collation) - but it handles dependencies for you.
Also you can keep a database project of the valid schema so you can use a universal template for your DBs should you have more than 1 to update, assuming all target DBs should end up with the same schema.
You can also use find/replace on the files in a database project should you wish to mass amend settings there (e.g. so you could create the project from the invalid database using schema compare, amend the project files, then toggle the source/target in the schema compare to push your changes back to the DB).
I read practically every answer and comment here so far. It got me to an easy solution by combining the responses made. So here is how it was easy for me to resolved:
Create a script of the database. Right-click database > Tasks > Generate Script. Be sure to include Schema and Data
Delete the database after you have saved the script. Right-click database > Delete
Remove the part of the script that will recreate the database, ie, delete everything upto the first line that starts with:
USE < DATABASENAME >
GO
Create the database 'manually', ie, right-click on Tables > Create database...
Run the script that sets the default collation that you want for the new empty database.
USE master;
GO
ALTER DATABASE << DatabaseName >>
COLLATE << INSERT COLATION REQUIRED >> ;
GO
Run the script you saved to recreate the database
Credit to
#Justin for providing the script to check the collation on the database, and how to update it
#RockScience for mentioning that the change on collation will only apply to new tables/objects
#Felix Mwiti Mugambi (acknowledging my fellow Kenyan :) ) for indicating the need to recreate the database. (I usually avoid dropping and creating for complex databases)
So we moved our SQL server to a new platform. During this move the primary and foreign keys were not transferred.
Is there a way I can script the keys from the old tables and add them to the new tables?
It doesn't look like they are going to redo it and just have us all the keys manually. Any speedy/safe way to do this is appreciated.
SQL Server 2008
Yup, you're going to love this. I have to drop and re-add FK's once in a while (like when I want to change an index that SQL hijacked for FK enforcement), so I wrote a view that will give me the drop and add statements:
select *, addqry = 'ALTER TABLE '+FKtable+' WITH ' + case when is_not_trusted = 1 then 'NO' else '' end + 'CHECK'
+ ' ADD CONSTRAINT ['+FK+'] FOREIGN KEY ('+FKcol+') '
+ ' REFERENCES '+PKtable+' ('+PKcol+')'+' ON UPDATE '+onUpdate+' ON DELETE '+onDelete
+ case when is_not_for_replication = 1 then ' NOT FOR REPLICATION' else '' end + ';'
+ case when is_disabled = 1 then ' ALTER TABLE '+FKtable+' NOCHECK CONSTRAINT ['+FK+'];' else '' end
,dropqry = 'ALTER TABLE '+FKtable+' DROP ['+FK+'];'
from (
select PKtable = object_schema_name(f.referenced_object_id)+'.'+object_name(f.referenced_object_id)
,PKtbl = object_name(f.referenced_object_id)
,PKcol = pc.name
,FKtable = object_schema_name(f.parent_object_id)+'.'+object_name(f.parent_object_id)
,FKtbl = object_name(f.parent_object_id)
,colseq = fk.constraint_column_id
,FKcol = fc.name
,FK = object_name(f.object_id)
,onUpdate = replace(f.update_referential_action_desc collate SQL_Latin1_General_CP1_CI_AS, '_', ' ')
,onDelete = replace(f.delete_referential_action_desc collate SQL_Latin1_General_CP1_CI_AS, '_', ' ')
,f.is_disabled
,f.is_not_trusted
,f.is_not_for_replication
from sys.foreign_key_columns as fk
join sys.foreign_keys f on fk.constraint_object_id = f.object_id
join sys.columns as fc on f.parent_object_id = fc.object_id and fk.parent_column_id = fc.column_id
join sys.columns as pc on f.referenced_object_id = pc.object_id and fk.referenced_column_id = pc.column_id
) t
Since you're dealing with primary key and foreign keys, I would use a (free) tool like SQL Server Database Tools (SSDT). This is a Microsoft tool that integrates with Visual Studio (if you have it - you don't need it). It will synch a target schema with a source schema. It does essentially what a tool like Red Gat Schema Compare does, except it's free. And it works very well. Using a tool like this will ensure your entire schema got moved over, not just PKs and FKs.
I have a database that is used to transfer data across the main production database when we import data from a third party.
I would like to add an Identity column to each table.
I know that the below SQL will do for a single table, how can I do it for all the tables in the database?
ALTER TABLE dbo.YourTable
ADD Id INT IDENTITY(1,1) NOT NULL
Many thanks
You'll have to do it one table at a time - there's no "magic" way to do it to all tables at once.
You can have SQL Server generate the T-SQL statements needed for that operation by inspecting the sys.tables catalog view - assuming you want to call that identity column Id for all tables:
SELECT
t.NAME,
'ALTER TABLE [' + SCHEMA_NAME(t.SCHEMA_ID) + '].[' + t.NAME +
'] ADD Id INT IDENTITY(1,1) NOT NULL'
FROM
sys.tables t
Now, copy & paste the resulting lines of this statement and execute those lines against your database - and you're done!
U can use 'sp_MSforeachtable 'And add to Every table in your Database
just run this query:
EXEC sp_MSforeachtable '
if not exists (select * from sys.columns
where object_id = object_id(''?'')
and name = ''ColName'')
begin
ALTER TABLE ? ADD ColName <DataType> NULL ; // or NOT NULL DEFAULT
<DefaultValue>;
end';
If you are using an Azure SQL,This Stored Procedure is not available under programmability.
Either you can port it from your master database from your on-prem sql server.Or use this link to the run the stored procedure
https://gist.github.com/metaskills/893599
I need to reset collation for all columns in all tables in the database:
I want to use default collation of database
I tried to change it under database properties:
but collation already setted in columns and it mean that i cannot overwrite it
anybody has script that can do it for me?
I've knocked together a script that should do a decent enough job (hopefully). Run the script in the appropriate database, with results as text. Then Copy & Paste the output into a script window to change the collation of each column:
declare #NewCollationName sysname
set #NewCollationName = 'Latin1_General_CS_AS'
select
'ALTER TABLE ' + QUOTENAME(SCHEMA_NAME(st.schema_id)) + '.' + QUOTENAME(st.name) +
' ALTER COLUMN ' + QUOTENAME(sc.name) + ' ' + styp.name + '(' +
CASE WHEN sc.max_length = -1 THEN 'max' ELSE CONVERT(varchar(10),sc.max_length) END +
') collate ' + #NewCollationName + '
go
'
from
sys.columns sc
inner join
sys.tables st
on
sc.object_id = st.object_id
inner join
sys.types styp
on
sc.user_type_id = styp.user_type_id
where
sc.collation_name is not null and
OBJECTPROPERTY(st.object_id,N'IsMSShipped')=0
One thing to note, however, is that the generated script won't work if the columns are the target of constraints or targetted by a schema bound object (view or function).
In such cases, you'd have to script out the dependent objects, drop them from the database, then run the script generated by the script above, and finally re-add the dependent objects.
See (Changing the Database Collation) http://msdn.microsoft.com/en-us/library/ms174269.aspx
ALTER DATABASE database_name COLLATE collation_name
The fastest way to reset a column would be to SET UNUSED the column, then add a column with the same name and datatype.
This will be the fastest way since both operations will not touch the actual table (only dictionary update).
The actual ordering of the columns will be changed (the reset column will be the last column). If your code rely on the ordering of the columns (it should not!) you can create a view that will have the column in the right order (rename table, create view with the same name as old table, revoke grants from base table, add grants to view).
The SET UNUSED method will not reclaim the space used by the column (whereas dropping the column will free space in each block).
Hope this helps.
A proposed script (can be found here) is meant to iterate through all tables in your DB and changing the collation to the desired one.
It is based on the script:
ALTER TABLE TABLENAME ALTER COLUMN COLUMNNAME varchar(100) COLLATE Latin1_General_CI_AS NULL
I have a requirement where I have to change collation of my DB for that I need to drop all the constraints and recreate them after running the collation change script at my DB. May I know how can I generatescript of all constraints of my DB?
SELECT top 1
'ALTER TABLE '+ SCHEMA_NAME(schema_id) + '.' + OBJECT_NAME(parent_object_id) +
' ADD CONSTRAINT ' + dc.name + ' DEFAULT(' + definition
+ ') FOR ' + c.name
FROM sys.default_constraints dc
INNER JOIN sys.columns c ON dc.parent_object_id = c.object_id AND dc.parent_column_id = c.column_id
script to generate all constraints
SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
get all constraints on db then filter on your table
This will get you all the constraints in the database, you can filter it by what you need:
SELECT OBJECT_NAME(OBJECT_ID) AS NameofConstraint,
SCHEMA_NAME(schema_id) AS SchemaName,
OBJECT_NAME(parent_object_id) AS TableName,
type_desc AS ConstraintType
FROM sys.objects
WHERE type_desc LIKE '%CONSTRAINT'
I think you might also need to look at any indices, statistics, etc. that might also keep you from dropping the column.
This can be done easily from SQL Server Management Studio.
Right-click on the database and go to Tasks, Generate Scripts....
This will bring up a script generation wizard that will generate DROP and CREATE scripts for whatever schema constructs that you select.
Select your database
Make sure that you select Script Drop to True
Select Tables
Select New Query Editor Window and click Finish.
You can program something like this using SMO or even easier is to just use the script wizard in SSMS. Go to your database in the Object Explorer and right-click on it. Select Tasks->Generate Scripts (NOT "Script Database as"). In the wizard you can make sure that constraints are scripted and remove other items. Check the generated script and make sure that it does what you need. If not, go through the wizard again making the necessary adjustments.