У меня есть две базы данных, одна с сопоставлением Latin1_General_CI_AI
, а другая с Latin1_General_CS_AS
.
Обе базы данных имеют расширенное свойство, называемое Version
, и для обеих установлено значение 1.
Если я запускаю следующий код:
IF ((SELECT value FROM sys.extended_properties WHERE name = 'Version') <> '1')
BEGIN
RAISERROR ('Wrong Version', 16, 1);
END
Я получаю сообщение об ошибке «Неверная версия» в базе данных с сопоставлением CS_AS
, но не в базе данных с сопоставлением CI_AI
. я
Я бы не ожидал получить ошибку ни на том, ни на другом.
Чтобы сделать это странным, если я побегу:
SELECT value
FROM sys.extended_properties
WHERE name = 'Version'
Я получаю значение 1 в обеих базах данных. Поэтому я не уверен, почему я получаю сообщение об ошибке.
Я также пробовал запускать collate
, что также не помогло
IF ((SELECT value FROM sys.extended_properties WHERE name = 'Version' collate Latin1_General_CI_AI) <> 1)
BEGIN
RAISERROR ('Wrong Version',16,1);
END
Привет @ThomA В рамках моего тестирования я попробовал int
1
, а также попробовал !=
вместо <>
, чтобы посмотреть, поможет ли это, но это та же проблема.
Попробуйте CAST(value AS int)
или CAST(value AS varchar(10))
, чтобы не проводить сравнения с sql_variant. например см. dbfiddle.uk/Ect2BS0O
Когда вы делаете
(SELECT value FROM sys.extended_properties WHERE name = 'Version') <> '1'
'1'
неявно приводится к sql_variant
(так как это имеет более высокий приоритет типа данных)
Это будет сравниваться как равное только в том случае, если сопоставление строк эффективно равно.
Когда значения sql_variant данных char, varchar, nchar или nvarchar сравниваются типы, их сопоставления сначала сравниваются на основе следующие критерии: LCID, версия LCID, флаги сравнения и идентификатор сортировки. Каждый из этих критериев сравнивается как целочисленное значение, и в порядок указан. Если все эти критерии равны, то фактический строковые значения сравниваются в соответствии с параметрами сортировки.
SELECT 'Returns a row'
WHERE CAST('1' COLLATE Latin1_General_CI_AS AS SQL_VARIANT) <>
CAST('1' COLLATE Latin1_General_CI_AI AS SQL_VARIANT)
Ты можешь сделать
(SELECT CAST(value AS varchar(10)) FROM sys.extended_properties WHERE name = 'Version') <> '1'
сначала преобразовать значение в строку, а затем получить обычную семантику сравнения строк (не беспокоясь о том, какое сопоставление использовалось при первом сохранении значения расширенного свойства)
Вы можете использовать значение приведения к varchar и использовать сопоставление для решения проблемы.
use [TestDB1]
IF ((SELECT cast( value as varchar(100)) collate Latin1_General_CS_AS FROM sys.extended_properties WHERE name = 'Version' ) <> '1')
BEGIN
RAISERROR ('Wrong Version',16,1);
END
use [TestDB2]
IF ((SELECT cast( value as varchar(100)) collate Latin1_General_CS_AS FROM sys.extended_properties WHERE name = 'Version' ) <> '1')
BEGIN
RAISERROR ('Wrong Version',16,1);
END
Вы можете создавать базы данных и addextendedproperty со следующими операторами:
CREATE DATABASE [TestDB1]
CONTAINMENT = NONE
ON PRIMARY
( NAME = N'TestDB1', FILENAME = N'C:\1\TestDB1.mdf' , SIZE = 8192KB , FILEGROWTH = 65536KB )
LOG ON
( NAME = N'TestDB1_log', FILENAME = N'C:\1\TestDB1_log.ldf' , SIZE = 8192KB , FILEGROWTH = 65536KB )
COLLATE Latin1_General_CI_AI
USE [master]
GO
EXEC [TestDB1].sys.sp_addextendedproperty @name=N'Version', @value=N'1'
GO
CREATE DATABASE [TestDB2]
CONTAINMENT = NONE
ON PRIMARY
( NAME = N'TestDB2', FILENAME = N'C:\1\TestDB2.mdf' , SIZE = 8192KB , FILEGROWTH = 65536KB )
LOG ON
( NAME = N'TestDB2_log', FILENAME = N'C:\1\TestDB2_log.ldf' , SIZE = 8192KB , FILEGROWTH = 65536KB )
COLLATE Latin1_General_CS_AS
USE [master]
GO
EXEC [TestDB2].sys.sp_addextendedproperty @name=N'Version', @value=N'1'
GO
Учитывая, что это значение 1, почему бы не сравнить его с
int
1
, а не сvarchar
'1'
?