"NVARCHAR(255) is null" brings collation conflict - sql

I'm having a temp procedure:
CREATE PROCEDURE
#update_ListItemEntityNumberValueAndLocalizations(
#modelPrefix NVARCHAR(255),
#definitionNeutralName NVARCHAR(255),
#listItemNeutralValue NVARCHAR(255),
#newNumberValue float,
#listItemEnName NVARCHAR(255),
#listItemDeName NVARCHAR(255))
In this procedure there is the following if statement:
if(#listItemEnName is not null)
And at this line I get the following error:
Cannot resolve the collation conflict between
"SQL_Latin1_General_CP1_CI_AS" and "Latin1_General_CI_AS" in the is
not operation.
Does anyone know why this happens and how I can avoid it?
UPDATE: Database collation is SQL_Latin1_General_CP1_CI_AS
Why does a "is null" needs the collation?
Is there a way to cast the null or set the collation of the parameter?

Use an explicit collate clause
if(#listItemEnName COLLATE Latin1_General_CI_AS is not null)
Or alternatively dependant upon what the stored procedure does switching the context to USE tempdb; then creating the temporary stored procedure and then switching the context back to your original database might work as below.
You are creating a temporary stored procedure so the parameter will be regarded as having the collation of tempdb. However tempdb must have a different collation from your user database.
As far as I can tell from experimentation when the stored procedure is first created it is bound to the database context in use (even if it is later ALTER-ed from a different database context).
. e.g. I am on a case sensitive collation but if I create the following procedure in a case insensitive database
CREATE PROC #Foo2
AS
IF 'a' = 'A'
PRINT 'Yes'
SELECT *
FROM sys.database_files
No matter what database I run it from it or if I alter it when USE-ing a different database it continues to print "Yes" and return information about the original database's files.

Related

Syntax issue on the source

I'm migrating a SQL Server 2008 database to SQL Server 2019, I have used Microsoft Data Migration Assistant, to look for search any breaking changes, issues or syntax errors.
I getting errors for some of my procedures:
Object [dbo].[PROCEDURE1] has syntax errors. Must declare the variable or parameter "#SINI". Error number 70590. For more details, please see: Line 9, Column 16.
This is my procedure:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[PROCEDURE1]
#Refer AS varchar,
#Ret Decimal OUTPUT
AS
DECLARE #SIni AS Decimal
SET #SIni= (SELECT Ini FROM Table1 WHERE Refer = #Refer)
SET #Ret = #SINI
Probably you have a server with case sensitive collation. As is explained in the documentation, the identifiers for variables, GOTO labels, temporary stored procedures, and temporary tables are in the default collation of the server instance.. You may check this with the following simple statement:
SELECT SERVERPROPERTY('collation');
But, to fix the error, use the correct case-sensitive variable name:
...
SET #Ret = #SIni
...
As an additional note, declare your data types with the appropriate length (as #Larnu commented). The length attribute is optional, and in case of parameter declaration the SQL Server assigns 1 as length, so the #Refer parameter has data type varchar(1).

SSIS SQL task stopped working after upgrading to 2012 from 2008

I´m looking for any information what could cause a package (that is working on multiple 2008 r2 environments) stop working when upgraded to 2012.
All the SQL-tasks have started to malfunction and I do not know why.
Here is an example .
I get a collation error, even though I recreated the database to be in right collation and remade the query, so it does not join anymore.
How is it possible to get a collation error without join!
use master
DECLARE #db varchar(100)
DECLARE #tid varchar(3)
DECLARE #queryta varchar(max)
SET #db= ?
SET #tid = ?
SET #queryta='
SELECT smt.nro COLLATE database_default as yr,
smt.type COLLATE database_default AS tyyppi,
ISNULL(CAST(CONVERT(date,smt.dt1) AS VARCHAR),''1799-12-30'') COLLATE database_default AS dt,
ISNULL(CAST(CONVERT(date,smt.dt12 AS VARCHAR),''1799-12-30'') COLLATE database_default AS dt2
FROM [mydatabase].[dbo].[table] as smt
WHERE smt.T_Id='''+#tid+'''
'
exec(#queryta)
The error:
[Execute SQL Task] Error: Executing the query "use master DECLARE #db
varchar(100) DECLARE #..." failed with the following error: "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 "Finnish_Swedish_CI_AS" in
add operator.". Possible failure reasons: Problems with the query,
"ResultSet" property not set correctly, parameters not set correctly,
or connection not established correctly.
I am using SQL Server Data Tools to debug.
This is dribing me crazy, any and all help apprecieated!!
EDITED TO ENFORCE COLLATION, NO CHANGE
#RemusRusanu Is right. The server collation is Finnish_Swedish_CI_AS and the database collations are Latin something. The error is a bug in SSIS behavior as the query is valid and runs in the management studio.
I can not use use master command and 3 part naming to access the right database, the one with different collation. No amount of casting or enforcing collation seems to fix it (the server should have been set up with Latin something collation as all the DB´s seem to use it).
The solution was simply to change use master -> use mydatabase
Thanks for #RemusRusanu

Selecting data from a different schema within a stored procedure

Consider this:
CREATE PROCEDURE [dbo].[setIdentifier](#oldIdentifierName as varchar(50), #newIdentifierName as varchar(50))
AS
BEGIN
DECLARE #old_id as int;
DECLARE #new_id as int;
SET #old_id = (SELECT value FROM Configuration WHERE id = #oldIdentifierName);
SET #new_id = (SELECT value FROM Configuration WHERE id = #newIdentifierName);
IF #old_id IS NOT NULL AND #new_id IS NOT NULL
BEGIN
UPDATE Customer
SET type = #new_id
WHERE type = #old_id;
END;
END
[...]
EXECUTE dbo.setIdentifier '1', '2';
What this does is create a stored procedure that accepts two parameters which it then uses to update a Customer table.
The problem is that the entire script above runs within a schema other than "dbo". Let's just assume the schema is "company1". And when the stored procedure is called, I get an error from the SELECT statement, which says that the Configuration table cannot be found. I'm guessing this is because MS SQL by default looks for tables within the same schema as the location of the stored procedure, and not within the calling context.
My question is this:
Is there some option or parameter or switch of some kind that will
tell MS SQL to look for tables in the "caller's default schema" and
not within the schema that procedure itself is stored in?
If not,
what would you recommend? I don't really want to prefix the tables
with the schema name, because it would be kind of unflexible to do
that. So I'm thinking about using dynamic sql (and the schema_name()
function which returns the correct value even within the procedure),
but I am just not experienced enough with MS SQL to construct the
proper syntax.
It would be a tad more efficient to explicitly specify the schema name. And generally speaking, schema's are mainly used to divide a database into logical area's. I would not anticipate on tables schema-hopping often.
Regarding your question, you might want to have a look at the 'execute as' documentation on msdn, since it allows to explicitly control your execution context.
I ended up passing the schema name to my script as a property on the command line for the "sqlcmd" command. Like this:
C:/> sqlcmd -vSCHEMANAME=myschema -imysqlfile
In the SQL script I can then access this variable like this:
SELECT * from $(SCHEMANAME).myTable WHERE.... etc
Not quite as flexible as dynamic sql, but "good enough" as it were.
Thanks all for taking time to respond.

Facing error of "The default schema does not exist." when executing runtime query inside sp using exec()

i have made a runtime query inside a sp and am exceuting the query within the sp using exec(), but when creating the sp i am getting the error
The default schema does not exist.
The SP is:
CREATE PROCEDURE MySP
#tableName varchar(100)
AS
BEGIN
SET NOCOUNT ON;
declare #selectQuery varchar(MAX)
set #selectQuery = 'select * from ' + #tableName
exec(#selectQuery)
end
kindly help
Use CREATE PROCEDURE dbo.MySP
The user you are logged in as must have a non existent default schema.
DEFAULT_SCHEMA can be set to a schema that does not currently exist in the database.
Also you should use quotename(#tableName) and a parameter type of sysname rather than varchar(100) to avoid SQL injection or just errors from non standard object names.
You could change your default schema:
ALTER USER [YOURDOMAIN\HotTester] WITH DEFAULT_SCHEMA=[dbo]
GO
then avoiding having to include [dbo]. in the CREATE PROCEDURE
It is probably because the default schema associated with the User creating the SP no longer exists or the user no longer has access to the schema.
Although, I thought SQL Server defaulted to the dbo schema. Maybe try to qualify the schema for the Stored Proc.
e.g
Create Procedure dbo.MySP
I ran into this "The default schema does not exist" error on an INSERT statement. It didn't help to prefix it with the dbo schema even though the table was in the dbo schema.
The default schema for this user was a custom one. It did exist, and the user could query a table inside it.
I finally figured out that I had to add a schema with that same name in tempdb. I don't really understand why this was needed, but hopefully it will help someone else who searches for this error message.

Sql server 2005 acting case sensitive inspite of case insensitive collation

I am having following issue.Even after case insensitive collation. SQL server is treating #Result and #result differently. Am i missing something.Please help.
SELECT DATABASEPROPERTYEX('OA_OPTGB_0423', 'Collation') SQLCollation;
SQL_Latin1_General_CP1_CI_AS
DECLARE #Result varchar(2000)
SELECT TOP 1 #result = addr.address_id
FROM dbo.address addr
JOIN dbo.company_address compadd ON addr.address_id = compadd.address_id
ORDER BY addr.address_id desc
...throws this error:
Msg 137, Level 15, State 1, Line 2
Must declare the scalar variable "#result".
Edit:-
This same query works in my local machine.I tried it and got no error.
From MSDN:
Identifier Collation
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.
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. Therefore, the
identifiers for variables, GOTO
labels, and temporary tables are in
the default collation of the instance.
So even though you're attempting to declare the collation of the database, variables are always going to use the default collation of your SQL Server instance.
If you've just reinstalled your database into a new instance, you should consider either upgrading your code to comply with the new collation (probably what I would do), or else follow this document on how to change the instance collation.
Really though, it seems a bit sloppy to have randomly cased variable references ;)
Collation deals with data (values); not identifier names.
There is no reason for your sample to fail unless you're running the statements as separate batches as your declarations only have scope local to the batch.
If you're running the statements one-at-a-time .... there's your problem!
Otherwise check what you have configured as a batch separator; the default is GO