SQL Server stored procedure case sensitive? - sql-server

I have a case sensitive SERVER (SQL_Latin1_General_CP1_CS_AS) but the Database is Case insensitive (SQL_Latin1_General_CP1_CI_AS).
If I try to create the following stored procedure on the database, I get the error "Must declare the scalar variable "#test"."
CREATE PROCEDURE [dbo].[sp_Test] (#TEST int) as
begin
SELECT #test
end
GO
But as I stated the database itself is not case sensitive. Im assuming this is documented somewhere that stored procedures follow the sensitivity of the server but I cannot find a reference anywhere. Can anyone point me to where I would find some docs about this? (Yes I tried google, but im not finding anything)

You are right. Database collation does not control variables name case sensitivity - server collation does.
Any other object name (e.g. table, view, column) follows database collation rules. In your situation, that means case insensitive, since your database is CI (case insensitive).
From the SQL Server Books Online:
COLLATE (Transact-SQL)
The collation of an identifier depends on the level at which it is defined.
Identifiers of instance-level objects, such as logins and database names, are assigned the default collation of the instance.
Identifiers of objects within a database, such as tables, views, and column names, are assigned the default collation of the database.
For example, two tables with names different only in case may be created in a database with case-sensitive collation, but may not be created in a database with case-insensitive collation. For more information, see Database Identifiers.
The identifiers for variables, GOTO labels, temporary stored procedures, and temporary tables are in the default collation of the server instance.
Variables, GOTO labels, temporary stored procedures, and temporary tables can be created when the connection context is associated with one database, and then referenced when the context has been switched to another database.
You can check your server collation using:
SELECT SERVERPROPERTY('collation');
SQL_Latin1_General_CP1_CI_AS
(1 row(s) affected)
See also
MSDN forums: Why are my SP's throwing a case error when pushing to a db using BIN collation?
Case sensitive variables in SQL Server
Case sensitive variable names in SQL Server?

Related

SQL Server Stored Procedure, View and Table Unique Identifier

Where does SQL Server save its unique identifier for stored procedures, views and tables? When I rename a stored procedure, how does SQL Server know what stored procedure to rename?
I'm hoping it's something like a row number that I can select in a query. By looking at the INFORMATION_SCHEMA, I'm able to get a table of objects but can't figure out how SQL Server keeps track of any changes
I would guess you are talking about object_id. SELECT * FROM sys.objects has all objects and their ID's
You can also do:
select OBJECT_ID('your_proc_name_here')
to see what the object_id is.
As for tracking changes, there is not a table that keeps what your proc was prior to an alter statement or tells you what the view definition was 2 weeks ago. You would have to make a user defined table and write logic to handle that, or use a VCS.

Is there a way to know which objects are actually being used in SQL Server 2008 R2

I found here Quick way to find usages of DB Objects in SQL Server 2008? a few ways I can check dependencies of objects in a SQL Server 2008 R2 database.
But is there a way to know if an object is actually being used? In other words, I see that a stored procedure uses a certain table, but how to I know if that stored procedure is ever executed, and if so, by who?
I'm asking because I came to a place in which there are A BUNCH of stored procedures and tables, and nobody knows what is being used.
For tables, you can use index statistics:
SELECT getdate() AS RunTime
, DB_NAME(i.database_id) as DatabaseName
, OBJECT_NAME(i.object_id, i.database_id) as ObjectName
, *
FROM sys.dm_db_index_usage_stats AS i
WHERE object_id > 100
This works for all tables because SQL Server keeps index stats even for heaps.
Stored procedures are harder. You could instrument them, like:
create table SPCalls (name sysname);
go
alter procedure dbo.YourSP
as
insert SPCalls ('YourSP');
....

sql server collation for stored procedures generated script

I have generated the stored procedures script for a database which is "Modern_Spanish_CI_AS". I run that script without problem in one server which has "SQL_Latin1_General_CP1_CI_AS" collation, but in another server which has "Modern_Spanish_BIN" collation, the script fails because some variables are declared #userLogin (or something else) and they are used #userlogin. CAPS vs no caps
There is no difference whether script is like:
EXEC dbo.sp_executesql #statement = N'my sp body'
or script is like:
CREATE PROCEDURE [dbo].MySpName
I have executed the following to ensure the database collation is the correct one:
SELECT DATABASEPROPERTYEX('MyDatabase','collation');/*returns "Modern_Spanish_CI_AS"*/
I'm not allowed to change server collation.
What could I do (other than change the case of the thousands of expressions) in order to succesfully run the script and ensure the sp's will work fine??? And, will there be an impact at runtime when a sp try to compare varchar values???
Thanks in advance
You must change the case of the thousands of expressions, learn your lesson, and in future always test your code in case sensitive collation servers.

How to remove Case Sensitive check in SQL Server 2008?

I just installed SQL Server 2008 and imported AdventureWorksDatabase (for SQL 2005, as for 2008 that didn't worked).
It is now enforcing case sensitivity when I searched for any tables, views etc
Hence Person.contact table when written throws an error of Invalid column name, but when Person.Contact is written it shows all rows.
Plus the intellisense too doesn't work great.
Case sensitivity is controlled by the collation the database uses - check this by querying the system catalog views:
select name, collation_name
from sys.databases
A collation name will be something like: Latin1_General_CI_AS
The _CI_ part is telling me here that it's a case insensitive collation. If you see a _CS_ then it's a case sensitive collation.
You can change a database's default collation using:
ALTER DATABASE AdventureWorks COLLATE .......
and pick any valid collation here - use one with a _CI_ to get a case-insensitive collation.
Trouble is: even if you change the collation on the database level, certain tables might still have individual column that had a specific collation defined when the table was created. You could also change all of these, but that's going to be a bigger undertaking. See this article for more info and a script to check and possibly change individual columns in your tables.
The reason the intellisense might not be working properly is that the case sensitivity of database objects per se is controlled by the server collation - which can again be different from any database default.
To find out what the server's collation is, use:
SELECT SERVERPROPERTY('Collation')
Changing the server's system collation is quite a messy process and requires you to use the original setup.exe as explained here.
The problem here is Case Sensitivity of the table name Contact. You should set collation_name of the Database AdventureWorks as Latin1_General_CI_AS
Check for collation_name:
SELECT name, collation_name
FROM sys.databases
WHERE name = 'AdventureWorks';
GO
If the collation_name is Latin1_General_BIN or Latin1_General_CS_AS change it to Latin1_General_CI_AS
ALTER DATABASE AdventureWorks
COLLATE Latin1_General_CI_AS ;
GO
If the Database has locked to do this action "The database could not be exclusively locked to perform the operation." . Alter the Database to Single User
ALTER DATABASE AdventureWorks SET SINGLE_USER WITH ROLLBACK IMMEDIATE
and do
ALTER DATABASE AdventureWorks
COLLATE Latin1_General_CI_AS ;
GO
Revert back the Database to Multi User finally
ALTER DATABASE AdventureWorks SET MULTI_USER WITH ROLLBACK IMMEDIATE
Or
You can change the Collation in Database Properties.

Database name while referencing tables - Sybase

How do I get away with hardcoding the database name in referencing a table within a stored procedure. For example there are two databases db1 and db2. I am writing a stored procedure in db2 which references two tables, one from db1 and another from db2. Both are on the same sybase server.
If I understand your question correctly, on the one hand, in your stored procedure you can refer to the table in the same database directly by name
SELECT ...
FROM table_in_db2
You can refer to a table in database db1 by prefixing the database name and an empty owner:
SELECT ...
FROM db1..table_in_db1
On the other hand, if you want to avoid hard-coding database names in the procedure you might create a view in database db2 that references the db1 table:
CREATE VIEW view_in_db2
AS
SELECT *
FROM db1..table_in_db1
and use that in the procedure:
SELECT ...
FROM view_in_db2
You need to keep the code portable, involve 2 databases, but avoid referencing databases by name. Then you can create proxy tables (or proxy views, if such views exist in 12.5). Refer to proxy tables as to local objects.
This will work, but will require some extra care, every time you move/change databases. But anyway the separation of concerns you are after can be achieved.

Resources