Запрос расширенных свойств в SQL Server с параметрами сортировки CS_AS не дает правильных результатов

У меня есть две базы данных, одна с сопоставлением 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

Учитывая, что это значение 1, почему бы не сравнить его с int1, а не с varchar'1'?

Thom A 17.04.2023 20:19

Привет @ThomA В рамках моего тестирования я попробовал int1, а также попробовал != вместо <>, чтобы посмотреть, поможет ли это, но это та же проблема.

Arthur Quenneville 17.04.2023 20:21

Попробуйте CAST(value AS int) или CAST(value AS varchar(10)), чтобы не проводить сравнения с sql_variant. например см. dbfiddle.uk/Ect2BS0O

Martin Smith 17.04.2023 20:37
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
3
70
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Когда вы делаете

(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

Другие вопросы по теме