Оператор с неопределенным типом? или зачем встречаться? - PullRequest
3 голосов
/ 14 января 2020

Я создал простую таблицу для хранения пар имя-значение.

create table ifr_nvpairs
(
    name varchar(255) PRIMARY KEY,
    type char(5),
    string varchar(255),
    bit_value bit,
    int_value bigint,
    dec_value decimal(12,2),
    float_value float,
    date_value datetime,
    char_value varchar(255)

);

Существует ограничение и триггеры, гарантирующие, что

insert ifr_nvpairs(name,bit_value) values ('bitValue',1);

приведет к

bitValue    BIT     1   true    (null)  (null)  (null)  (null)  (null)

Я пропущу их здесь для краткости и дам несколько полных вставок:

INSERT INTO "ifr_nvpairs" ("name", "type", "string", "bit_value", "int_value", "dec_value", "float_value", "date_value", "char_value") VALUES ('bitValue', 'BIT  ', '1', true, null, null, null, null, null);
INSERT INTO "ifr_nvpairs" ("name", "type", "string", "bit_value", "int_value", "dec_value", "float_value", "date_value", "char_value") VALUES ('charValue', 'CHAR ', 'Hugo ist nett!', null, null, null, null, null, 'Hugo ist nett!');
INSERT INTO "ifr_nvpairs" ("name", "type", "string", "bit_value", "int_value", "dec_value", "float_value", "date_value", "char_value") VALUES ('dateValue', 'DATE ', '2020-01-13 00:00:00.000', null, null, null, null, '2020-01-13 00:00:00', null);
INSERT INTO "ifr_nvpairs" ("name", "type", "string", "bit_value", "int_value", "dec_value", "float_value", "date_value", "char_value") VALUES ('decValue', 'DEC  ', '8.15', null, null, 8.15, null, null, null);
INSERT INTO "ifr_nvpairs" ("name", "type", "string", "bit_value", "int_value", "dec_value", "float_value", "date_value", "char_value") VALUES ('floatValue', 'FLOAT', '3.14159', null, null, null, 3.14, null, null);
INSERT INTO "ifr_nvpairs" ("name", "type", "string", "bit_value", "int_value", "dec_value", "float_value", "date_value", "char_value") VALUES ('intValue', 'INT  ', '42', null, 42, null, null, null, null);

Для удобства пользователей я хотел создать выборку, которая возвращает значение в сохраненном типе.

Мой подход был

select 
    case type
    when 'BIT' then  bit_value  
    when 'INT' then  int_value  
    when 'DEC' then  dec_value  
    when 'FLOAT' then  float_value
    when 'DATE' then  date_value 
    when 'CHAR' then  char_value
    end result 
    from ifr_nvpairs where name='bitValue';

Я бы не удивился, если бы произошла ошибка. Но результатом всегда является дата и время.

Почему? И есть ли возможность в SQL выбрать тип гетерогена?

TIA Jo

Ответы [ 2 ]

2 голосов
/ 14 января 2020

A SQL select запрос возвращает фиксированный набор столбцов. Каждый столбец имеет фиксированный тип, определенный, когда запрос скомпилирован .

A case выражение также возвращает один тип. По правилам преобразования типов этот тип обычно является «наиболее конкретным c» (это правила SQL). При наличии множества типов, которые вы предоставили, результат правил выглядит как datetime.

. Вы не можете вернуть несколько разных типов в одном столбце, если не укажите значение как * 1011. * (на самом деле это просто другой тип).

Вы не можете делать то, что хотите, с обычным SQL. Одна из возможностей - это Dynami c SQL. Другим был бы другой подход, который не требовал бы такой логики c.

1 голос
/ 14 января 2020

A CASE выражение использует приоритет типа данных (Transact- SQL) для определения типа возвращаемых данных:

SQL Сервер использует следующий порядок приоритета для типов данных:

  1. пользовательские типы данных (максимальные)
  2. sql_variant
  3. xml
  4. datetimeoffset
  5. datetime2
  6. datetime
  7. smalldatetime
  8. date
  9. time
  10. float
  11. real
  12. десятичный
  13. деньги
  14. smallmoney
  15. bigint
  16. int
  17. smallint
  18. tinyint
  19. bit
  20. ntext
  21. text
  22. image
  23. timestamp
  24. uniqueidentifier
  25. nvarchar (включая nvarchar (max))
  26. nchar
  27. varchar (включая varchar (max))
  28. char
  29. varbinary (включая varbinary (max))
  30. binary (самый низкий)

Тип с наивысшим приоритетом будет turn, что в данном случае равно datetime (с приоритетом 6).

Что касается вашего вопроса "А есть ли возможность в SQL выбрать тип гетерогена?" , как упоминалось в комментариях, sql_variant существует, но я рекомендую против этого. Он имеет очень мало случаев использования и любые сравнения требуют, чтобы значение было явно преобразовано. Поскольку вы не можете использовать синтаксис, такой как CONVERT(SQL_VARIANT_PROPERTY(YourColumn,'BaseType'),YourColumn), вам придется использовать динамический c SQL, чтобы сделать это, и вы все равно не можете иметь несколько типов данных в одном столбце.

Если вы нужно отображать разные типы данных, делайте это в разных столбцах.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...