2017-07-09 77 views
1

我使用REXTESTER來編寫一段SQL Server代碼。排序規則衝突SQL Server varchar存儲過程參數

它說,它的SQL Server 2014 Express Edition的多數民衆贊成在使用...

這裏是最小的代碼,以使該消息。

CREATE PROCEDURE #CONVERT_TIME_TO_24_HR 
(
    @TIME_STRING varchar(4) 
) 
AS 
BEGIN 
    DECLARE @AMPM as varchar(2); 
    SET @AMPM = RIGHT(@TIME_STRING,2); 
    IF @AMPM = 'am' 
    SELECT 2 
END 
GO 

這裏的錯誤:

Error(s), warning(s): 
Cannot resolve the collation conflict between "SQL_Latin1_General_CP1_CI_AS" and "Latin1_General_CI_AS" in the equal to operation. 

如果@TIME_STRING剛剛宣佈,而不是存儲過程我沒有問題的參數。由於我無法控制SQL Server實例,因此我該如何解決此問題?

這裏有一個forked version時,它不是一個參數 - 沒有任何問題

DECLARE @TIME_STRING varchar(4); 
DECLARE @AMPM as varchar(2); 
SET @AMPM = RIGHT(@TIME_STRING,2); 
    IF @AMPM = 'am' 
    SELECT 2 

回答

2

這會發生,因爲服務器/數據庫/列的排序規則具有不同的值(可能是服務器和數據庫)。你可以通過在排序中明確添加來修復它:

CREATE PROCEDURE #CONVERT_TIME_TO_24_HR (
    @TIME_STRING varchar(4) 
) AS 
BEGIN 
    DECLARE @AMPM as varchar(2); 
    SET @AMPM = RIGHT(@TIME_STRING,2); 
    IF @AMPM = 'am' COLLATE SQL_Latin1_General_CP1_CI_AS ; 
    SELECT 2; 
END; 

我承認這不是一個普通的列。在你自己的系統上,默認的排序規則可能都匹配。我不知道爲什麼Rextester的設計師會有不同的默認排序規則。

+0

謝謝你一堆。它工作的一種享受。雖然不是很直觀。看起來奇怪的是你在IF上而不是在聲明上。特別是如果你有多個IF! – JGFMK

+1

@JGFMK。 。 。這不是'如果'。它在不斷。我認爲使得常量具有與存儲數據相同的排序規則更明智,然後反過來。但是正如我想的那樣,常量會從變量聲明中得到不同的排序規則,這很奇怪。現在爲時過早,我覺得這太難了。 –

+0

啊好吧...所以我也需要它在'pm'字面上... – JGFMK

1

另一個解決方案(戈登解決方案的+1)將使用COLLATE DATABASE_DEFAULT這意味着整理當前數據庫。下面的例子是基於以下歸類:

  1. 'Latin1_General_CI_AS' 爲tempdb數據庫
  2. 'Romanian_CI_AS' 當前 - DbCollat​​eDiffThanTempDbCollat​​ - 數據庫。

由於CREATE PROCEDURE #...語句DbCollateDiffThanTempDbCollat數據庫的上下文中與COLLATE DATABASE_DEFAULT選項執行這意味着IF @AMPM = 'am' COLLATE DATABASE_DEFAULT相當於與IF @AMPM = 'am' COLLATE Romanian_CI_AS(在此上下文中)。

SELECT DATABASEPROPERTYEX('tempdb', 'Collation') 
/* 

--------------------- 
Latin1_General_CI_AS 
*/ 
GO 

CREATE DATABASE DbCollateDiffThanTempDbCollat 
COLLATE Romanian_CI_AS 
GO 
USE DbCollateDiffThanTempDbCollat 
GO 
SELECT DATABASEPROPERTYEX('DbCollateDiffThanTempDbCollat', 'Collation') 
GO 
/* 

-------------- 
Romanian_CI_AS 
*/ 

USE DbCollateDiffThanTempDbCollat -- Current database for COLLATE DEFAULT_DATABASE is DbCollateDiffThanTempDbCollat -> COLLATE Romanian_CI_AS 
GO 
CREATE PROCEDURE #CONVERT_TIME_TO_24_HR 
(
    @TIME_STRING varchar(4) 
) 
AS 
BEGIN 
    DECLARE @AMPM as varchar(2); 
    SET @AMPM = RIGHT(@TIME_STRING,2); 
    IF @AMPM = 'am' COLLATE DATABASE_DEFAULT 
    SELECT 2 
END 
GO 
/* 
Command(s) completed successfully. 
*/