{"id":70501,"date":"2017-04-06T16:15:05","date_gmt":"2017-04-06T16:15:05","guid":{"rendered":"https:\/\/www.simple-talk.com\/?p=70501"},"modified":"2021-08-24T13:39:25","modified_gmt":"2021-08-24T13:39:25","slug":"questions-sql-server-collations-shy-ask","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/databases\/sql-server\/t-sql-programming-sql-server\/questions-sql-server-collations-shy-ask\/","title":{"rendered":"Questions About SQL Server Collations You Were Too Shy to Ask"},"content":{"rendered":"<ol>\n<li><a href=\"#post-70501-_Toc479001442\">What is a SQL Server collation?<\/a><\/li>\n<li><a href=\"#post-70501-_Toc479001443\">How do I find the collations supported on a SQL Server instance?<\/a><\/li>\n<li><a href=\"#post-70501-_Toc479001444\">How do I identify Unicode-only collations?<\/a><\/li>\n<li><a href=\"#post-70501-_Toc479001445\">What are the differences between Windows collations and SQL Server collations?<\/a><\/li>\n<li><a href=\"#post-70501-_Toc479001446\">How do I set the collation at the server level?<\/a><\/li>\n<li><a href=\"#post-70501-_Toc479001447\">How do I configure a database\u2019s default collation?<\/a><\/li>\n<li><a href=\"#post-70501-_Toc479001448\">How do I assign a collation to a column?<\/a><\/li>\n<li><a href=\"#post-70501-_Toc479001449\">How do I specify a collation when querying data?<\/a><\/li>\n<li><a href=\"#post-70501-_Toc479001450\">How do I query columns with different collations?<\/a><\/li>\n<li><a href=\"#post-70501-_Toc479001451\">How do I create a foreign key on columns with different collations?<\/a><\/li>\n<li><a href=\"#post-70501-_Toc479001452\">How do collations affect temporary tables?<\/a><\/li>\n<li><a href=\"#post-70501-_Toc479001453\">How do I know what collations to use?<\/a><\/li>\n<\/ol>\n<h2><a id=\"post-70501-_Toc479001442\"><\/a>1. What is a SQL Server collation?<\/h2>\n<p>A collation is a configuration setting that determines how the database engine should treat character data at the server, database, or column level. SQL Server includes a large set of collations for handling the language and regional differences that come with supporting users and applications in different parts of the world.<\/p>\n<p>Each collation serves two purposes. The first is to provide a character set that defines the bit pattern associated with each character.<\/p>\n<p>SQL Server stores character data using either one byte or two bytes per character, depending on the column\u2019s data type and assigned collation. For example, European languages require only a single-byte character set, which supports up to 256 bit patterns. On the other hand, many Asian languages include thousands of characters and require a double-byte character set, which supports up to 65,536 bit patterns.<\/p>\n<p>Collations are intricately tied to the data types assigned to character columns. In SQL Server, you can configure a character column with a Unicode data type (<strong>nchar<\/strong>, <strong>nvarchar<\/strong>, or <strong>ntext<\/strong>) or non-Unicode data type (<strong>char<\/strong>, <strong>varchar<\/strong>, or <strong>text<\/strong>). For Unicode types, the character bit patterns conform to international standards that define a double-byte encoding scheme for mapping most of the world\u2019s written languages, ensuring that the same bit pattern is always associated with the same character, regardless of the underlying environment.<\/p>\n<p>Most collations support both Unicode and non-Unicode character data, although some support only Unicode data. Each collation that supports non-Unicode data is associated with a code page that defines the bit patterns for the non-Unicode characters. The collation must point to a code page supported by the underlying operating system; however, multiple collations can point to the same code page if they share the same character set. Unicode-only collations do not require code pages because they conform to the universal encoding model.<\/p>\n<p>To view the code page associated with a collation, you can use the <strong>COLLATIONPROPERTY<\/strong> system function, as shown in the following example:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">SELECT COLLATIONPROPERTY('Modern_Spanish_100_CS_AS', 'CodePage');<\/pre>\n<p>The function takes two arguments. The first is the name of the collation, in this case, <strong>Modern_Spanish_100_CS_AS<\/strong>, and the second is the <strong>CodePage<\/strong> property. The <strong>SELECT<\/strong> statement returns the value <strong>1252<\/strong>, which is the code page identifier. On my system, 894 collations share this code page. (I\u2019m running SQL Server 2016 Developer Edition on Windows 10).<\/p>\n<p>The second purpose of the SQL Server collation is to specify the rules that govern how character data is sorted and compared, taking into account not only language and regional conventions, but also the options specific to a collation, such as case-sensitivity and accent-sensitivity.<\/p>\n<p>Each collation enforces its own sorting and comparison rules, whether or not it points to the same code page as other collations. For this reason, query results can differ when accessing identical data in two columns configured with different collations, even if those collations are based on the same language.<\/p>\n<p>In SQL Server, you can specify a collation at the server level, database level, or column level, and you can specify collations within your queries. Keep in mind, however, that you can run into query and performance issues when working with multiple collations at the same time.<\/p>\n<h2><a id=\"post-70501-_Toc479001443\"><\/a>2. How do I find the collations supported on a SQL Server instance?<\/h2>\n<p>To view a list of the available collations, you can use the <strong>sys.fn_helpcollations<\/strong> system table function to retrieve the collation names and their descriptions, as shown in the following example:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">SELECT name, description\r\n  FROM sys.fn_helpcollations();<\/pre>\n<p>On my system, the statement returns 3,887 collations that support a wide range of languages, with numerous collations for each language family. For example, the following table shows a number of the collations available to the Tibetan family (but not all):<\/p>\n<table class=\"table--tight\">\n<thead>\n<tr>\n<td>\n<p>Name<\/p>\n<\/td>\n<td>\n<p>description<\/p>\n<\/td>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>\n<p>Tibetan_100_CI_AI_SC<\/p>\n<\/td>\n<td>\n<p>Tibetan-100, case-insensitive, accent-insensitive, kanatype-insensitive, width-insensitive, supplementary characters<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>Tibetan_100_CI_AI_WS_SC<\/p>\n<\/td>\n<td>\n<p>Tibetan-100, case-insensitive, accent-insensitive, kanatype-insensitive, width-sensitive, supplementary characters<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>Tibetan_100_CI_AI_KS_SC<\/p>\n<\/td>\n<td>\n<p>Tibetan-100, case-insensitive, accent-insensitive, kanatype-sensitive, width-insensitive, supplementary characters<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>Tibetan_100_CI_AI_KS_WS_SC<\/p>\n<\/td>\n<td>\n<p>Tibetan-100, case-insensitive, accent-insensitive, kanatype-sensitive, width-sensitive, supplementary characters<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>Tibetan_100_CI_AS_SC<\/p>\n<\/td>\n<td>\n<p>Tibetan-100, case-insensitive, accent-sensitive, kanatype-insensitive, width-insensitive, supplementary characters<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>Tibetan_100_CI_AS_WS_SC<\/p>\n<\/td>\n<td>\n<p>Tibetan-100, case-insensitive, accent-sensitive, kanatype-insensitive, width-sensitive, supplementary characters<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>Tibetan_100_CI_AS_KS_SC<\/p>\n<\/td>\n<td>\n<p>Tibetan-100, case-insensitive, accent-sensitive, kanatype-sensitive, width-insensitive, supplementary characters<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>Tibetan_100_CI_AS_KS_WS_SC<\/p>\n<\/td>\n<td>\n<p>Tibetan-100, case-insensitive, accent-sensitive, kanatype-sensitive, width-sensitive, supplementary characters<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>Tibetan_100_CS_AI_SC<\/p>\n<\/td>\n<td>\n<p>Tibetan-100, case-sensitive, accent-insensitive, kanatype-insensitive, width-insensitive, supplementary characters<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>Tibetan_100_CS_AI_WS_SC<\/p>\n<\/td>\n<td>\n<p>Tibetan-100, case-sensitive, accent-insensitive, kanatype-insensitive, width-sensitive, supplementary characters<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Most language families include numerous collations, each configured with specific options, such as width-sensitivity and accent-sensitivity. When specifying a collation in your T-SQL script, you must use the name exactly as it is returned by the <strong>sys.fn_helpcollations<\/strong> function. The collation name includes the supported language and, in some cases, the collation version. For example, the collations in the table above are all specific to the Tibetan language and are all version 100.<\/p>\n<p>The remaining codes in each collation name (such as <strong>_CS_AI_WS_SC<\/strong>) indicate the options preconfigured on the collation. For example, <strong>CI<\/strong> means case-insensitive and <strong>AS<\/strong> means accent-sensitive. The <strong>description<\/strong> column shows what the option codes mean. For more detailed information, see the Microsoft article \u201c<a href=\"https:\/\/docs.microsoft.com\/en-us\/sql\/relational-databases\/collations\/collation-and-unicode-support\">Collation and Unicode Support<\/a>.\u201d<\/p>\n<h2><a id=\"post-70501-_Toc479001444\"><\/a>3. How do I identify Unicode-only collations?<\/h2>\n<p>Some collations support only Unicode characters and consequently can be used only with the <strong>nchar<\/strong>, <strong>nvarchar<\/strong>, or <strong>ntext<\/strong> data types, either within column definitions or when querying data from those columns. Unfortunately, you cannot tell from the collation name whether or not it is Unicode-only, but you can use a combination of the <strong>sys.fn_helpcollations<\/strong> and <strong>COLLATIONPROPERTY<\/strong> system functions to retrieve a list of Unicode-only collations:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">SELECT name, description\r\n  FROM sys.fn_helpcollations()\r\n  WHERE COLLATIONPROPERTY(name, 'CodePage') = 0;<\/pre>\n<p>On my system, the <strong>SELECT<\/strong> statement returns 510 rows. You can, of course, narrow down the search to specific languages, but you get the idea. You use the <strong>COLLATIONPROPERTY<\/strong> system function to find the collations with a <strong>CodePage<\/strong> value of <strong>0<\/strong>. Because a Unicode-only collation does not point to a code page, the database engine simply returns a <strong>0<\/strong>, rather than a <strong>NULL<\/strong> value or some obscure number, or worse still, an error.<\/p>\n<h2><a id=\"post-70501-_Toc479001445\"><\/a>4. What are the differences between Windows collations and SQL Server collations?<\/h2>\n<p>SQL Server supports two collation types: Windows collations and SQL Server collations. You can tell them apart by their names. All SQL Server collation names begin with <strong>SQL_<\/strong>.<\/p>\n<p>Each collation type supports both character-based collations and binary-based. Once again, you can distinguish them by their names. Binary-based collations end with either <strong>_BIN<\/strong> or <strong>_BIN2<\/strong>.<\/p>\n<p>Character-based Windows collations represent the bulk of the collations available to SQL Server. The collations are based on the Windows <em>locales<\/em> available to the host operating system where SQL Server is installed. A locale is a collection of information specific to a location or culture. Windows uses locales to customize the interface for regional groups of users.<\/p>\n<p>Windows collations in SQL Server use the same code pages as the Windows locales, as well as the same sorting and comparison rules. However, SQL Server provides collations for only a subset of Windows locales, and each collation supports only a subset of the attributes available to the Windows locale. The Windows collations in SQL Server are concerned with locales only in terms of data management.<\/p>\n<p>Windows collations use the same algorithm for sorting and comparing both Unicode and non-Unicode data, making it easier to work with character data stored with different data types. You can retrieve a list of the character-based Windows collations available to your system by running the following <strong>SELECT<\/strong> statement:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">SELECT name, description\r\n  FROM sys.fn_helpcollations()\r\n  WHERE name NOT LIKE 'sql_%' AND name NOT LIKE '%_bin%';<\/pre>\n<p>All we\u2019re doing here is taking advantage of how collations are named by eliminating any names that start with <strong>sql_<\/strong> and end with <strong>_bin<\/strong> or <strong>_bin2<\/strong>. On my system, I came up with 3,552 character-based Windows collations.<\/p>\n<p>Binary-based collations represent the other type of Windows collations. They are similar to the character-based collations except in how the data is sorted. For non-Unicode data, sorting is based on the coded numerical values (code points) defined by the Windows locale. For Unicode data, sorting is based on the code points defined by the Unicode standard, so locale is not a factor. In either case, the sort order is simpler to enforce, helping to improve application performance.<\/p>\n<p>SQL Server supports the two types of binary-based collations:<\/p>\n<ul>\n<li><strong>BIN:<\/strong> The database engine compares the first character of a data value by code point and the remaining characters by their bit patterns. This type represents the original approach to binary-based collations in SQL Server.<\/li>\n<li><strong>BIN2:<\/strong> The database engine compares all characters based on code points. This type represents the newer generation of binary-based collations.<\/li>\n<\/ul>\n<p>To view a list of binary-based Windows collations, we can use the following <strong>SELECT<\/strong> statement, which returns 258 collations on my system:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">SELECT name, description\r\n  FROM sys.fn_helpcollations()\r\n  WHERE name NOT LIKE 'sql_%' AND name LIKE '%_bin%';<\/pre>\n<p>In case you\u2019re wondering how many of the binary-based Windows collations are Unicode only, we can run the following <strong>SELECT<\/strong> statement, which gives me 30 collations:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">SELECT name, description\r\n  FROM sys.fn_helpcollations()\r\n  WHERE COLLATIONPROPERTY(name, 'CodePage') = 0\r\n  \u00a0 AND name NOT LIKE 'sql_%' AND name LIKE '%_bin%';<\/pre>\n<p>Now we move into the SQL Server collations, which were created before SQL Server supported windows collations. Microsoft keeps these collations on-hand for backward compatibility with older versions of SQL Server and legacy applications. You should use not use SQL Server collations for new development work.<\/p>\n<p>That said, let\u2019s take a closer look at SQL Server collations, should you need to use them. Like Windows collations, SQL Server collations use a code page for non-Unicode characters and follow the Unicode standard for the rest.<\/p>\n<p>But here\u2019s where things get tricky with SQL Server collations. The database engine applies non-Unicode sorting rules to the non-Unicode data, and Unicode sorting rules to the Unicode data, which can give you inconsistent results when working with character data stored in columns with different data types. Again, you should be using SQL Server collations only to support those legacy databases and applications.<\/p>\n<p>To learn what character-based SQL Server collations an instance supports, we can run the following query, which gives me 73 collations:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">SELECT name, description\r\n  FROM sys.fn_helpcollations()\r\n  WHERE name LIKE 'sql_%' AND name NOT LIKE '%_bin%';<\/pre>\n<p>Our final collation type is the binary-based SQL Server collation, of which there are few. These collations work much like the binary-based Windows collations, except with the limitations that come with the character-based SQL Server collations. To view a list of the binary-based SQL Server collations available to an environment, we can run the following <strong>SELECT<\/strong> statement, which returns only four rows on my system:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">SELECT name, description\r\n  FROM sys.fn_helpcollations()\r\n  WHERE name LIKE 'sql_%_bin%';<\/pre>\n<p>It should also be noted that SQL Server does not support Unicode-only SQL Server collations, either character-based or binary-based. For example, if we were to run the following <strong>SELECT<\/strong> statement:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">SELECT name, description\r\n  FROM sys.fn_helpcollations()\r\n  WHERE COLLATIONPROPERTY(name, 'CodePage') = 0\r\n  \u00a0 AND name LIKE 'sql_%';<\/pre>\n<p>We would end up with an empty result set.<\/p>\n<h2><a id=\"post-70501-_Toc479001446\"><\/a>5. How do I set the collation at the server level?<\/h2>\n<p>You set the collation at the server level when you initially install SQL Server. The collation serves as the default collation for all system databases and user databases, unless a different collation is specified at the database or column level. You can assign any collation at the server instance, except Unicode-only collations.<\/p>\n<p>If you\u2019re uncertain what collation has been assigned to a SQL Server instance, you can use the <strong>SERVERPROPERTY<\/strong> system function to find out:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">SELECT SERVERPROPERTY('collation');<\/pre>\n<p>On my system, the <strong>SELECT<\/strong> statement returns the collation <strong>SQL_Latin1_General_CP1_CI_AS<\/strong>, which was the default when I installed SQL Server. The SQL Server installation wizard used this collation because I live in the US and the underlying Windows operating system uses the <strong>English<\/strong> <strong>(United<\/strong> <strong>States)<\/strong> locale. Microsoft selects this collation as the default to maintain compatibility with earlier versions of SQL Server and with applications developed against those versions.<\/p>\n<p>If you want to use a collation other than the default when installing SQL Server, be sure to change the collation on the <strong>Collation<\/strong> tab of the wizard\u2019s <strong>Server<\/strong> <strong>Configuration<\/strong> screen.<\/p>\n<p>You should try your best to get the server collation right when you install SQL Server because changing it after the fact is no small feat. You must take such steps as backing up the data, rebuilding the <strong>master<\/strong> database, recreating the user databases and all the objects in them, and importing the data into the newly created tables.<\/p>\n<p>Fortunately, instead of changing the server collation, you can assign a different default collation to your user databases, and you can assign a specific collation to a character column.<\/p>\n<h2><a id=\"post-70501-_Toc479001447\"><\/a>6. How do I configure a database\u2019s default collation?<\/h2>\n<p>When you define a user database, you can set the default collation as part of the database definition. If you don\u2019t specify the collation, SQL Server uses the collation assigned to the server instance.<\/p>\n<p>You cannot assign a collation to a system database, nor can you directly modify its collation. The only way you can change the collation on a system database is to change the server-level collation.<\/p>\n<p>To specify a collation when creating a user database, you add a <strong>COLLATE<\/strong> clause to the database definition. The clause must point to one of the collations supported by your SQL Server instance. As with server-level collations, you cannot specify a Unicode-only collation. To test this out, let\u2019s try to create a database using the <strong>Indic_General_100_CS_AS<\/strong> collation:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">USE master;\r\n  GO\r\n  DROP DATABASE IF EXISTS TestCollations;\r\n  GO\r\n  CREATE DATABASE TestCollations\r\n  COLLATE Indic_General_100_CS_AS;\r\n  GO<\/pre>\n<p>Because <strong>Indic_General_100_CS_AS<\/strong> is a Unicode-only collation, the database engine returns the following error message:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">Collation 'Indic_General_100_CS_AS' is supported on Unicode data types only and cannot be set at the database or server level.<\/pre>\n<p>The issue is easily remedied by specifying a collation that is not Unicode-only:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">USE master;\r\n  GO\r\n  DROP DATABASE IF EXISTS TestCollations;\r\n  GO\r\n  CREATE DATABASE TestCollations\r\n  COLLATE Latin1_General_100_CS_AI;\r\n  GO<\/pre>\n<p>This time, the <strong>CREATE<\/strong> <strong>DATABASE<\/strong> statement will run and the specified collation will be assigned to the database. SQL Server will apply the collation to all metadata within that database. The collation also serves as the default for character columns, variable names, and other character data within the database.<\/p>\n<p>We can confirm that the database was created using the specified collation by running the following query:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">SELECT collation_name\r\n  FROM sys.databases\r\n  WHERE NAME = 'TestCollations';<\/pre>\n<p>As expected, the statement returns <strong>Latin1_General_100_CS_AS<\/strong>, which means that the database engine will enforce both case-sensitivity and accent-sensitivity when sorting and comparing character data.<\/p>\n<p>Another way we can verify the collation is to use the <strong>DATABASEPROPERTYEX<\/strong> system function:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">SELECT DATABASEPROPERTYEX('TestCollations', 'Collation');<\/pre>\n<p>The <strong>SELECT<\/strong> statement again returns the returns the <strong>Latin1_General_100_CS_AS<\/strong> collation.<\/p>\n<p>We can also use the <strong>COLLATE<\/strong> clause in an <strong>ALTER<\/strong> <strong>DATABASE<\/strong> statement if we want to change the default collation:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">ALTER DATABASE TestCollations\r\n  COLLATE Latin1_General_100_CI_AS;\r\n  GO<\/pre>\n<p>When we change the database collation, the database engine updates the collation for all the character columns in the system tables, as well as existing character parameters and scalar values returned by stored procedures and user-defined functions. The database engine also applies the collation to new columns configured with character data types. However, SQL Server does not change the collations of existing character columns in user-defined tables.<\/p>\n<h2><a id=\"post-70501-_Toc479001448\"><\/a>7. How do I assign a collation to a column?<\/h2>\n<p>As with database definitions, you can add the <strong>COLLATE<\/strong> clause when defining a character column. In this way, you can apply a specific collation to the column\u2019s data, without impacting the rest of the database. You can use the <strong>COLLATE<\/strong> clause in either a <strong>CREATE<\/strong> <strong>TABLE<\/strong> statement or <strong>ALTER<\/strong> <strong>TABLE<\/strong> statement. When you specify a collation on a column, you override the database\u2019s collation, which is applied by default to all character columns.<\/p>\n<p>For columns configured with the <strong>nchar<\/strong>, <strong>nvarchar<\/strong>, or <strong>ntext<\/strong> data type, you can assign any type of collation, including Unicode-only collations. For <strong>char<\/strong>, <strong>varchar<\/strong>, and <strong>text<\/strong> columns, you must use a collation that supports non-Unicode characters, which rules out Unicode-only collations.<\/p>\n<p>To assign a collation to a column, you include the <strong>COLLATE<\/strong> clause within the column\u2019s definition, as shown in the following example:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">USE TestCollations;\r\n  GO\r\n  DROP TABLE IF EXISTS LastNames;\r\n  GO\r\n  CREATE TABLE LastNames(\r\n  \u00a0 NameID INT IDENTITY PRIMARY KEY,\r\n  \u00a0 LastName VARCHAR(50) COLLATE Traditional_Spanish_CI_AS NOT NULL);\r\n  INSERT INTO LastNames(LastName)\r\n  VALUES('Carri\u00f3n'), ('Carrion'), ('carri\u00f3n'), ('carrion'),\r\n  \u00a0 ('Chaves'), ('Chavira'), ('C\u00faneo'), ('Cuneo'), ('c\u00faneo');<\/pre>\n<p>In this case, we\u2019re configuring the <strong>LastName<\/strong> column with the <strong>Traditional_Spanish_CI_AS<\/strong> collation, which is case-insensitive, but accent-sensitive. Now let\u2019s query the character data:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">SELECT * FROM LastNames\r\n  ORDER BY LastName;<\/pre>\n<p>The <strong>SELECT<\/strong> statement returns the following results:<\/p>\n<table class=\"table--tight\">\n<thead>\n<tr>\n<td>\n<p>NameID<\/p>\n<\/td>\n<td>\n<p>LastName<\/p>\n<\/td>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>\n<p>2<\/p>\n<\/td>\n<td>\n<p>Carrion<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>4<\/p>\n<\/td>\n<td>\n<p>carrion<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>3<\/p>\n<\/td>\n<td>\n<p>carri\u00f3n<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>1<\/p>\n<\/td>\n<td>\n<p>Carri\u00f3n<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>8<\/p>\n<\/td>\n<td>\n<p>Cuneo<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>9<\/p>\n<\/td>\n<td>\n<p>c\u00faneo<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>7<\/p>\n<\/td>\n<td>\n<p>C\u00faneo<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>5<\/p>\n<\/td>\n<td>\n<p>Chaves<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>6<\/p>\n<\/td>\n<td>\n<p>Chavira<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Because of the assigned collation, the database engine treats uppercase and lowercase letters as the same, and treats accented and unaccented letters as different. But something else is going on here. The database engine also treats \u201cc\u201d and \u201cch\u201d as separate letters, which is why C\u00faneo is listed before Chaves.<\/p>\n<p>You can change a column\u2019s collation by updating the table definition, unless the column is being referenced by an index, computed column, check constraint, foreign key constraint, or distribution statistics. With that in mind, let\u2019s change the collation of the <strong>LastName<\/strong> column to <strong>Modern_Spanish_CI_AI<\/strong>, which is case-insensitive and accent-insensitive:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">ALTER TABLE LastNames\r\n  ALTER COLUMN LastName VARCHAR(50)\u00a0\r\n  \u00a0 COLLATE Modern_Spanish_CI_AI NOT NULL;<\/pre>\n<p>If we rerun the preceding <strong>SELECT<\/strong> statement, Chaves will now come before C\u00faneo, as shown in the following results:<\/p>\n<table class=\"table--tight\">\n<thead>\n<tr>\n<td>\n<p>NameID<\/p>\n<\/td>\n<td>\n<p>LastName<\/p>\n<\/td>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>\n<p>1<\/p>\n<\/td>\n<td>\n<p>Carri\u00f3n<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>2<\/p>\n<\/td>\n<td>\n<p>Carrion<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>3<\/p>\n<\/td>\n<td>\n<p>carri\u00f3n<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>4<\/p>\n<\/td>\n<td>\n<p>carrion<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>5<\/p>\n<\/td>\n<td>\n<p>Chaves<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>6<\/p>\n<\/td>\n<td>\n<p>Chavira<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>7<\/p>\n<\/td>\n<td>\n<p>C\u00faneo<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>8<\/p>\n<\/td>\n<td>\n<p>Cuneo<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>9<\/p>\n<\/td>\n<td>\n<p>c\u00faneo<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Notice that, even though the collation is case-insensitive and accent-insensitive, the database engine still lists the names with an initial capital letter first for each sorted group. You\u2019ll find that the case-insensitive collations are not consistent in how they treat the first letter. Some will prioritize values with an initial capital letter, some will prioritize values with an initial lowercase letter, and some will not prioritize either.<\/p>\n<p>At some point, you might want to change a column\u2019s collation back to the database\u2019s default collation. To do so, you can use the <strong>database_default<\/strong> keyword instead of the actual collation name (which is currently <strong>Latin1_General_100_CI_AS<\/strong>):<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">ALTER TABLE LastNames\r\n  ALTER COLUMN LastName VARCHAR(50)\u00a0\r\n  \u00a0 COLLATE database_default NOT NULL;<\/pre>\n<p>The <strong>database_default<\/strong> keyword saves you the trouble of having to look up the database\u2019s collation, should you not know it off the top of your head. And even if you do, the keyword is a lot easier to type. If we rerun our <strong>SELECT<\/strong> statement, the database engine now returns the following results:<\/p>\n<table class=\"table--tight\">\n<thead>\n<tr>\n<td>\n<p>NameID<\/p>\n<\/td>\n<td>\n<p>LastName<\/p>\n<\/td>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>\n<p>4<\/p>\n<\/td>\n<td>\n<p>carrion<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>2<\/p>\n<\/td>\n<td>\n<p>Carrion<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>3<\/p>\n<\/td>\n<td>\n<p>carri\u00f3n<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>1<\/p>\n<\/td>\n<td>\n<p>Carri\u00f3n<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>5<\/p>\n<\/td>\n<td>\n<p>Chaves<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>6<\/p>\n<\/td>\n<td>\n<p>Chavira<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>8<\/p>\n<\/td>\n<td>\n<p>Cuneo<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>9<\/p>\n<\/td>\n<td>\n<p>c\u00faneo<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>7<\/p>\n<\/td>\n<td>\n<p>C\u00faneo<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>For the <strong>Latin1_General_100_CI_AS<\/strong> collation, the database engine lists the name that starts with a lowercase letter first in each sorted group (e.g., <em>carrion<\/em> then <em>Carrion<\/em>), which is the opposite of the <strong>Modern_Spanish_CI_AI<\/strong> collation. The <strong>Traditional_Spanish_CI_AS<\/strong> collation is inconsistent in this regard (e.g., <em>Carrion<\/em> then <em>carrion<\/em> vs. <em>c\u00faneo<\/em> then <em>C\u00faneo<\/em>).<\/p>\n<p>Despite the fact that the collations <strong>Latin1_General_100_CI_AS<\/strong>, <strong>Traditional_Spanish_CI_AS<\/strong>, and <strong>Modern_Spanish_CI_AI<\/strong> sort data differently, they are all based on code page 1252, which means that no matter which collation is specified, the characters all map to the same set of bit patterns.<\/p>\n<p>If you want to view a column\u2019s collation, you can query the <strong>sys.columns<\/strong> catalog view:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">SELECT collation_name\r\n  FROM sys.columns\r\n  WHERE OBJECT_NAME(object_id) = 'LastNames'\r\n  \u00a0 AND name = 'LastName';<\/pre>\n<p>Because we had configured the column with the database\u2019s default collation, the statement returns the <strong>Latin1_General_100_CI_AS<\/strong> collation.<\/p>\n<h2><a id=\"post-70501-_Toc479001449\"><\/a>8. How do I specify a collation when querying data?<\/h2>\n<p>You can also use the <strong>COLLATE<\/strong> clause directly in your queries. For example, suppose we\u2019ve assigned the <strong>Latin1_General_100_CI_AS<\/strong> collation to our database and its columns, but we want to return the data sorted according to the rules of the <strong>Traditional_Spanish_CI_AS<\/strong> collation. We need only add the <strong>COLLATE<\/strong> clause to the <strong>SELECT<\/strong> statement\u2019s <strong>ORDER<\/strong> <strong>BY<\/strong> clause:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">SELECT * FROM LastNames\r\n  ORDER BY LastName COLLATE Traditional_Spanish_CI_AS;<\/pre>\n<p>As the following results show, the names are now sorted according to the <strong>Traditional_Spanish_CI_AS<\/strong> collation, which is case-insensitive and accent-sensitive, with the \u201cc\u201d and \u201cch\u201d treated as separate letters:<\/p>\n<table class=\"table--tight\">\n<thead>\n<tr>\n<td>\n<p>NameID<\/p>\n<\/td>\n<td>\n<p>LastName<\/p>\n<\/td>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>\n<p>2<\/p>\n<\/td>\n<td>\n<p>Carrion<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>4<\/p>\n<\/td>\n<td>\n<p>carrion<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>3<\/p>\n<\/td>\n<td>\n<p>carri\u00f3n<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>1<\/p>\n<\/td>\n<td>\n<p>Carri\u00f3n<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>8<\/p>\n<\/td>\n<td>\n<p>Cuneo<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>9<\/p>\n<\/td>\n<td>\n<p>c\u00faneo<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>7<\/p>\n<\/td>\n<td>\n<p>C\u00faneo<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>5<\/p>\n<\/td>\n<td>\n<p>Chaves<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>6<\/p>\n<\/td>\n<td>\n<p>Chavira<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Now suppose we want to use the following <strong>SELECT<\/strong> statement to retrieve a specific name from the table:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">SELECT * FROM LastNames\r\n  WHERE LastName = 'carrion';<\/pre>\n<p>Because the collation is case-insensitive, but accent-sensitive, the results include only the following two names:<\/p>\n<table class=\"table--tight\">\n<thead>\n<tr>\n<td>\n<p>NameID<\/p>\n<\/td>\n<td>\n<p>LastName<\/p>\n<\/td>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>\n<p>2<\/p>\n<\/td>\n<td>\n<p>Carrion<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>4<\/p>\n<\/td>\n<td>\n<p>carrion<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>This time, let\u2019s specify the <strong>Traditional_Spanish_CS_AI<\/strong> collation when we query the table:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">SELECT * FROM LastNames\r\n  WHERE LastName = 'carrion' COLLATE Traditional_Spanish_CS_AI;<\/pre>\n<p>Because the new collation is case-sensitive, but accent-insensitive, we now get these results:<\/p>\n<table class=\"table--tight\">\n<thead>\n<tr>\n<td>\n<p>NameID<\/p>\n<\/td>\n<td>\n<p>LastName<\/p>\n<\/td>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>\n<p>3<\/p>\n<\/td>\n<td>\n<p>carri\u00f3n<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>4<\/p>\n<\/td>\n<td>\n<p>carrion<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>By specifying the collation, we can better control how the data is compared and the results sorted. But be aware that using collations in your queries can impact performance, especially when they involve large data sets. For example, a query might require additional table scans, depending on the nature of the data.<\/p>\n<h2><a id=\"post-70501-_Toc479001450\"><\/a>9. How do I query columns with different collations?<\/h2>\n<p>You might run into situations in which you need to query data from multiple columns that use different collations. The columns might be in the same table, different tables in the same database or different databases. In such cases, you can use the <strong>COLLATE<\/strong> clause in your queries to resolve possible incompatibilities.<\/p>\n<p>Let\u2019s look at a few examples to demonstrate how this works. We\u2019ll start by creating two tables in the <strong>TestCollations<\/strong> database (currently configured with the <strong>Latin1_General_100_CI_AS<\/strong> collation):<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">DROP TABLE IF EXISTS Emp1;\r\n  GO\r\n  CREATE TABLE Emp1(\r\n  \u00a0 EmpID INT IDENTITY PRIMARY KEY,\r\n  \u00a0 AltID CHAR(5) NOT NULL,\r\n  \u00a0 JobTitle VARCHAR(25) NOT NULL);\r\n  INSERT INTO Emp1(AltID, JobTitle)\r\n  VALUES('ab101', 'sales rep'), ('cd102', 'CEO'),\r\n  \u00a0 ('ef103', 'test engineer'), ('gh104', 'HR specialist');\r\n  DROP TABLE IF EXISTS Emp2;\r\n  GO\r\n  CREATE TABLE Emp2(\r\n  \u00a0 EmpID INT IDENTITY PRIMARY KEY,\r\n  \u00a0 AltID CHAR(5) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,\r\n  \u00a0 LoginID VARCHAR(25) NOT NULL);\r\n  INSERT INTO Emp2(AltID, LoginID)\r\n  VALUES('ab101', 'jchaves'), ('cd102', 'jdoe'),\r\n  \u00a0 ('ef103', 'rschmidt'), ('gh104', 'llee');<\/pre>\n<p>Notice that we\u2019ve assigned the <strong>SQL_Latin1_General_CP1_CI_AS<\/strong> collation to the <strong>AltID<\/strong> column in the <strong>Emp2<\/strong> table, but use the default database collation for everything else. Now let\u2019s try to join the tables based on the two <strong>AltID<\/strong> columns:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">SELECT e1.EmpID, e1.AltID, e1.JobTitle, e2.LoginID\r\n  FROM Emp1 e1 JOIN Emp2 e2\r\n  \u00a0 ON e1.AltID = e2.AltID\r\n  ORDER BY e1.EmpID;<\/pre>\n<p>Because the <strong>AltID<\/strong> columns are configured with different collations, the database engine returns the following error message:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">Cannot resolve the collation conflict between \"SQL_Latin1_General_CP1_CI_AS\" and \"Latin1_General_100_CI_AS\" in the equal to operation.<\/pre>\n<p>To get around this, we can add the <strong>COLLATE<\/strong> clause to the join condition when we reference the <strong>AltID<\/strong> column in the <strong>Emp2<\/strong> table:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">SELECT e1.EmpID, e1.AltID, e1.JobTitle, e2.LoginID\r\n  FROM Emp1 e1 JOIN Emp2 e2 ON\u00a0\r\n  \u00a0 e1.AltID = e2.AltID COLLATE Latin1_General_100_CI_AS\r\n  ORDER BY e1.EmpID;<\/pre>\n<p>Now the <strong>SELECT<\/strong> statement returns these results:<\/p>\n<table  class=\"table--tight\">\n<thead>\n<tr>\n<td>\n<p>EmpID<\/p>\n<\/td>\n<td>\n<p>AltID<\/p>\n<\/td>\n<td>\n<p>JobTitle<\/p>\n<\/td>\n<td>\n<p>LoginID<\/p>\n<\/td>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>\n<p>1<\/p>\n<\/td>\n<td>\n<p>ab101<\/p>\n<\/td>\n<td>\n<p>sales rep<\/p>\n<\/td>\n<td>\n<p>jchaves<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>2<\/p>\n<\/td>\n<td>\n<p>cd102<\/p>\n<\/td>\n<td>\n<p>CEO<\/p>\n<\/td>\n<td>\n<p>jdoe<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>3<\/p>\n<\/td>\n<td>\n<p>ef103<\/p>\n<\/td>\n<td>\n<p>test engineer<\/p>\n<\/td>\n<td>\n<p>rschmidt<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>4<\/p>\n<\/td>\n<td>\n<p>gh104<\/p>\n<\/td>\n<td>\n<p>HR specialist<\/p>\n<\/td>\n<td>\n<p>llee<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Because the <strong>AltID<\/strong> column in the <strong>Emp1<\/strong> table uses the database\u2019s default collation, we can instead specify the <strong>database_default<\/strong> keyword in our <strong>COLLATE<\/strong> clause, rather than the name of the collation:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">SELECT e1.EmpID, e1.AltID, e1.JobTitle, e2.LoginID\r\n  FROM Emp1 e1 JOIN Emp2 e2 ON\u00a0\r\n  \u00a0 e1.AltID = e2.AltID COLLATE database_default\r\n  ORDER BY e1.EmpID;<\/pre>\n<p>The <strong>SELECT<\/strong> statement returns the same results as the preceding statement, as does the next <strong>SELECT<\/strong> statement:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">SELECT e1.EmpID, e1.AltID, e1.JobTitle, e2.LoginID\r\n  FROM Emp1 e1 JOIN Emp2 e2 ON\u00a0\r\n  \u00a0 e1.AltID COLLATE SQL_Latin1_General_CP1_CI_AS = e2.AltID\r\n  ORDER BY e1.EmpID;<\/pre>\n<p>This time, we\u2019ve added the <strong>COLLATE<\/strong> clause to the first <strong>AltID<\/strong> reference, which achieves the same results, that is, to join the tables based on the <strong>AltID<\/strong> columns.<\/p>\n<p>Now let\u2019s look at what happens when we try to concatenate the <strong>LoginID<\/strong> and <strong>AltID<\/strong> columns in the <strong>Emp2<\/strong> table:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">SELECT EmpID, (LoginID + AltID) NewAltID\r\n  FROM Emp2 ORDER BY EmpID;<\/pre>\n<p>As with our join, we\u2019re working with two character columns configured with different collations. Not surprisingly, the database engine returns the following error message:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">Implicit conversion of varchar value to varchar cannot be performed because the collation of the value is unresolved due to a collation conflict between \"SQL_Latin1_General_CP1_CI_AS\" and \"Latin1_General_100_CI_AS\" in add operator.<\/pre>\n<p>Again, the <strong>COLLATE<\/strong> clause comes to the rescue:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">SELECT EmpID, (LoginID + AltID COLLATE database_default) NewAltID\r\n  FROM Emp2 ORDER BY EmpID;<\/pre>\n<p>The <strong>SELECT<\/strong> statement now returns the results we\u2019re looking for:<\/p>\n<table class=\"table--tight\">\n<thead>\n<tr>\n<td>\n<p>EmpID<\/p>\n<\/td>\n<td>\n<p>NewEmpID<\/p>\n<\/td>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>\n<p>1<\/p>\n<\/td>\n<td>\n<p>jchavesab101<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>2<\/p>\n<\/td>\n<td>\n<p>jdoecd102<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>3<\/p>\n<\/td>\n<td>\n<p>rschmidtef103<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>4<\/p>\n<\/td>\n<td>\n<p>lleegh104<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Again, being able to use the <strong>COLLATE<\/strong> clause in your queries is a handy tool, but keep in mind that the database engine has to work harder to make this happen.<\/p>\n<h2><a id=\"post-70501-_Toc479001451\"><\/a>10. How do I create a foreign key on columns with different collations?<\/h2>\n<p>Just like you cannot change the collation on a column that is being referenced by a foreign key, you cannot create a foreign key between two columns with different collations. To test this out, let\u2019s update the <strong>Emp1<\/strong> table we created above by adding a unique constraint to the <strong>AltID<\/strong> column so it can be referenced by a foreign key:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">ALTER TABLE Emp1\r\n  ADD CONSTRAINT uqAltID UNIQUE(AltID);<\/pre>\n<p>Now let\u2019s try to add a foreign key constraint to the <strong>AltID<\/strong> column in the <strong>Emp2<\/strong> table, referencing the <strong>AltID<\/strong> column in <strong>Emp1<\/strong> table:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">ALTER TABLE Emp2\r\n  WITH CHECK ADD CONSTRAINT fkAltID FOREIGN KEY(AltID)\r\n  \u00a0 REFERENCES Emp1(AltID);<\/pre>\n<p>Although both <strong>AltID<\/strong> columns are configured with the <strong>char(5)<\/strong> data type, when we try to run the <strong>ALTER<\/strong> <strong>TABLE<\/strong> statement, the database engine returns the following error message:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">Column 'Emp1.AltID' is not of same collation as referencing column 'Emp2.AltID' in foreign key 'fkAltID'.<\/pre>\n<p>One way to get around this is to alter the <strong>AltID<\/strong> column in <strong>Emp2<\/strong> table by changing the default collation to the same as the <strong>AltID<\/strong> column in <strong>Emp1<\/strong> table:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">ALTER TABLE Emp2\r\n  ALTER COLUMN AltID CHAR(5) COLLATE database_default NOT NULL;<\/pre>\n<p>In some cases, however, you will not be able to change the referencing column\u2019s collation. Another approach you might consider is to add a persisted computed column to the referenced table. For example, the following <strong>ALTER<\/strong> <strong>TABLE<\/strong> statement adds the <strong>AltID2<\/strong> computed column to the <strong>Emp1<\/strong> table:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">ALTER TABLE Emp1\r\n  ADD AltID2 AS AltID COLLATE SQL_Latin1_General_CP1_CI_AS PERSISTED;<\/pre>\n<p>The computed column contains the same data as <strong>AltID<\/strong> but specifies the <strong>SQL_Latin1_General_CP1_CI_AS<\/strong> collation. Next, we define a unique constraint on the <strong>AltID2<\/strong> column so it can be referenced by a foreign key:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">ALTER TABLE Emp1\r\n  ADD CONSTRAINT uqAltID UNIQUE(AltID2);<\/pre>\n<p>Finally, we add a foreign key constraint to the <strong>AltID<\/strong> column in the <strong>Emp2<\/strong> table, pointing to the <strong>AltID2<\/strong> column in the <strong>Emp1<\/strong> table:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">ALTER TABLE Emp2\r\n  WITH CHECK ADD CONSTRAINT fkAltID FOREIGN KEY(AltID)\r\n  \u00a0 REFERENCES Emp1(AltID2);<\/pre>\n<p>Although this will do the trick, adding a persisted computed column with a unique index adds overhead, so be sure this alternative won\u2019t have too serious an impact on your transactional workloads.<\/p>\n<h2><a id=\"post-70501-_Toc479001452\"><\/a>11. How do collations affect temporary tables?<\/h2>\n<p>If your SQL Server environment uses the same collation for the server, databases, and columns, then temporary tables present no problem in terms of collations. All the character columns throughout the database adhere to the same rules when performing sorts, comparisons, joins, concatenations, or other operations.<\/p>\n<p>However, if you use different collations for your databases and columns, you might run into unexpected results. For example, suppose we create and populate the following temporary table within a database configured with the <strong>Latin1_General_100_CI_AS<\/strong> collation:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">CREATE TABLE #Emp3(\r\n  \u00a0 AltID CHAR(5) NOT NULL,\r\n  \u00a0 LoginID VARCHAR(25) NOT NULL);\r\n  INSERT INTO #Emp3\r\n  VALUES('ab101', 'jchaves'), ('cd102', 'jdoe'),\r\n  \u00a0 ('ef103', 'rschmidt'), ('gh104', 'llee');<\/pre>\n<p>We might expect that the <strong>AltID<\/strong> column will use the same collation as the database, given that no collation has been specified, but that\u2019s not the case. Because temporary tables are stored in the <strong>tempdb<\/strong> database, they are assigned the same collation as the server, no matter what the database collation might be.<\/p>\n<p>We can test this scenario by running the following query:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">SELECT e1.EmpID, e1.AltID, e1.JobTitle, e3.LoginID\r\n  FROM Emp1 e1 JOIN #Emp3 e3\r\n  \u00a0 ON e1.AltID = e3.AltID\r\n  ORDER BY e1.EmpID;<\/pre>\n<p>In this case, we\u2019re joining the <strong>Emp1<\/strong> and <strong>#Emp3<\/strong> tables based on their <strong>AltID<\/strong> columns. When we run this statement, the database engine returns the following error message:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">Cannot resolve the collation conflict between \"SQL_Latin1_General_CP1_CI_AS\" and \"Latin1_General_100_CI_AS\" in the equal to operation.<\/pre>\n<p>Fortunately, we can get around this issue by including a <strong>COLLATE<\/strong> clause in our query, as we saw in earlier examples:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">SELECT e1.EmpID, e1.AltID, e1.JobTitle, e3.LoginID\r\n  FROM Emp1 e1 JOIN #Emp3 e3\r\n  \u00a0 ON e1.AltID = e3.AltID COLLATE database_default\r\n  ORDER BY e1.EmpID;<\/pre>\n<p>Now the <strong>SELECT<\/strong> statement runs with no problem and returns the results shown in the following table:<\/p>\n<table  class=\"table--tight\">\n<thead>\n<tr>\n<td>\n<p>EmpID<\/p>\n<\/td>\n<td>\n<p>AltID<\/p>\n<\/td>\n<td>\n<p>JobTitle<\/p>\n<\/td>\n<td>\n<p>LoginID<\/p>\n<\/td>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>\n<p>1<\/p>\n<\/td>\n<td>\n<p>ab101<\/p>\n<\/td>\n<td>\n<p>sales rep<\/p>\n<\/td>\n<td>\n<p>jchaves<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>2<\/p>\n<\/td>\n<td>\n<p>cd102<\/p>\n<\/td>\n<td>\n<p>CEO<\/p>\n<\/td>\n<td>\n<p>jdoe<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>3<\/p>\n<\/td>\n<td>\n<p>ef103<\/p>\n<\/td>\n<td>\n<p>test engineer<\/p>\n<\/td>\n<td>\n<p>rschmidt<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>4<\/p>\n<\/td>\n<td>\n<p>gh104<\/p>\n<\/td>\n<td>\n<p>HR specialist<\/p>\n<\/td>\n<td>\n<p>llee<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Another approach we can take is to create our temporary table using the same collation as that of the database:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">CREATE TABLE #Emp3(\r\n  \u00a0 AltID CHAR(5) COLLATE database_default NOT NULL,\r\n  \u00a0 LoginID VARCHAR(25) NOT NULL);\r\n  INSERT INTO #Emp3\r\n  VALUES('ab101', 'jchaves'), ('cd102', 'jdoe'),\r\n  \u00a0 ('ef103', 'rschmidt'), ('gh104', 'llee');<\/pre>\n<p>As with other table definitions, we simply include the <strong>COLLATE<\/strong> clause in the column definition, allowing us to create a join without having to deal with collation differences:<\/p>\n<pre class=\"theme:ssms2012-simple-talk lang:tsql decode: true\">SELECT e1.EmpID, e1.AltID, e1.JobTitle, e3.LoginID\r\n  FROM Emp1 e1 JOIN #Emp3 e3\r\n  \u00a0 ON e1.AltID = e3.AltID\r\n  ORDER BY e1.EmpID;<\/pre>\n<p>When working with different collations, any objects stored in the <strong>tempdb<\/strong> database can cause issues. Not only temporary tables, but also variables, temporary stored procedures, and <strong>GOTO<\/strong> labels.<\/p>\n<h2><a id=\"post-70501-_Toc479001453\"><\/a>12. How do I know what collations to use?<\/h2>\n<p>The ideal solution is to choose a collation when setting up SQL Server that can be used for all your user databases and character columns. Using one collation removes any issues you might encounter when querying the data in different ways. It can also be the best approach in terms of performance if multiple collations impact your queries. However, this approach works only if the same language and collation settings are appropriate for all your users and applications\u2014or at least a good majority of them.<\/p>\n<p>If you support multi-cultural environments, you\u2019ll need to take into account a number of considerations. To begin with, you should pick collations that support the most users, and you should use Unicode data types where possible because they can help avoid code page conversion issues. Just keep in mind the storage requirements that come with Unicode\u2019s two bytes per character.<\/p>\n<p>When you implement Unicode data types, you have the option of using Unicode-only collations for your columns and queries. This type of collation can be useful when you\u2019re supporting client applications installed on older operating systems or when the applications or client drivers don\u2019t recognize the new Windows collations. Because Unicode-only collations don\u2019t use code pages, the applications won\u2019t try to map to incorrect bit patterns or adhere to conflicting rules. Instead, both the client and server treat all character data according to the Unicode standards.<\/p>\n<p>However, using Unicode data types with Unicode-only collations is not always an option, in which case, you might need to select your collations based on your client applications or their environments. For example, you might choose SQL Server collations because they can support the legacy systems. Depending on the circumstances, a good strategy might be to assign a SQL Server collation to the server or at least to the user databases, as applicable.<\/p>\n<p>Of course, you should upgrade the client operating system, application, or provider, when possible, but that might not always be a practical solution.<\/p>\n<p>If you\u2019re developing an entirely new data-driven application, you should stick with Windows collations, implementing Unicode data types and Unicode-only collations if and when they make sense. But be sure to keep performance and maintenance in mind, especially when you\u2019re mixing Unicode and non-Unicode data (or single-byte and double-byte data) or when your queries result in code page conversions between the client and server.<\/p>\n<p>The bottom line is that you must keep your client applications and users at the forefront of your thinking when choosing collations. You should also strive to keep things as simple as possible. The more collations you assign to a database, the harder the database engine might have to work. For large data sets, you should test various scenarios to determine their impact on performance, maintenance, and storage, and be sure to look at where code page conversions might be occurring and where conflicts could arise.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Of course we all like our colleagues to think that we know everything there is to know about SQL Server Collations.  However, the truth is that it is a rather complicated topic to fully understand and the cost of getting collation wrong can be great. If only one could ask certain questions on forums or at conferences without blushing. Help is at hand, because  Robert Sheldon once again makes the  complicated seem simple by answering those questions that you were too shy to ask&hellip;<\/p>\n","protected":false},"author":221841,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[143527,143531],"tags":[5771],"coauthors":[6779],"class_list":["post-70501","post","type-post","status-publish","format-standard","hentry","category-database-administration-sql-server","category-t-sql-programming-sql-server","tag-too-shy"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/70501","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/221841"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=70501"}],"version-history":[{"count":4,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/70501\/revisions"}],"predecessor-version":[{"id":70543,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/70501\/revisions\/70543"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=70501"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=70501"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=70501"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=70501"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}