Schemas have nothing to do with collation. Also, it would certainly help to know what is meant by "scripts starts failing". Please post the exact and full error message(s) to the question.
For the moment, based on the following two pieces of info:
The scripts are failing, not just returning unexpected / fewer results,
and:
You said that you can have two sets of scripts, not that you already do have (or at least have tried)
I am guessing that the procs have inconsistent references to the table and/or schema names in terms of casing. For example, the actual object being Sales.Table1
but referenced in one or more procs as Sales.table1
(only difference is the t in Table1). That is not something that can be fixed via a COLLATE
clause in a query. That requires fixing the code to use the proper casing. In fact, if you are going to deploy to instances that are case-sensitive, then it would be best to update your development (and test / QA / Staging) instances to also use a case-sensitive default collation at the database level. If your code can be deployed on instances using a binary collation, then perhaps use a binary collation. This will help you catch these types of errors very early in the development cycle.
Additionally, using a case-sensitive or even binary collation (ending in _BIN2
, not _BIN
) for the database and leaving the instance-level collation as case-insensitive (or just something different than the database default collation) will help you identify potential errors in queries related to temp tables.
In the end, you definitely shouldn't need multiple sets of scripts to handle different collations, especially if this is an issue with creating procedures that fail due to using a different casing on columns names but not tables (which results in an immediate error as it will find the table but not the column), or an issue with executing the procedure if there is a difference in casing for the table name as deferred name resolution will allow the proc to be created but will error upon execution.
NOW, regarding temp tables, the answer is not necessarily to use COLLATE DATABASE_DEFAULT
. It all depends on what your app is trying to accomplish for each string column affected. (And FYI: this part is the same, even if you deploy the full database setting a specific collation and aren't having a problem running a script that creates schemas / objects in a DB with any random collation).
If any affected column uses the database's default collation (i.e. does not specify a collation in the CREATE TABLE
statement), and the app doesn't require a particular collation for this specific operation/query, then yes, use COLLATE DATABASE_DEFAULT
next to each predicate / concatenation / reference in the query containing the temp table.
However, if an affected column is given a specific collation when the table is created, or if the operation / query requires a specific collation (i.e. a filter that must be case-insensitive no matter what), then you should use COLLATE {specific_collation_name}
next to each predicate / concatenation / reference in the query containing the temp table.
Based on info added to the question:
The scenario is pretty much what I had guessed based on the previous info:
- Your scripts are being deployed to existing databases (outside of your control)
- The errors are coming from column names being referenced in the stored procedures with different casing than they were created with.
Hence, the advice doesn't really change: You only need one set of scripts, the set with the column references matching the casing used when creating the tables. So if a table has a column named TimeStamp
, then referencing that column as Timestamp
in the code is an error (as it would be in many / most programming languages). You need to fix your source procs, leaving you will a single, correct set of scripts that will work everywhere.
You should also consider either changing the development instance (or just database at the very least, which is easier to change anyway) to use a binary collation. Or, deploy to an instance (or database) using a binary collation as part of your CI process (if you have one), or just as a matter of practice if you don't have an automated process. In either case, you will catch casing differences much earlier in the development process.
Not using temp tables will avoid collation differences in [tempdb]
. As for table variables, those should be fine as their string columns, by default, use the database's default collation. You can still run into an issue if you have a string column set to a collation different from the database's default and compare it to a column in a table variable that wasn't created with that same collation. In that case, you just use COLLATE {collation_name}
everywhere that issue is happening, specifying the collation used for the column from the user table.
CREATE DATABASE
) or are simply adding your objects to any random existing DB.