Что в спецификации SQL или PostgreSQL объясняет сравнение массивов с примитивами? - PullRequest
0 голосов
/ 04 февраля 2019

Я хочу понять, почему именно вы можете сравнивать пустые значения как равные внутри массивов, а не как примитивы.

Например, следующий запрос демонстрирует:

SELECT NULL = NULL AS does_not_equal
     , NULL::bool = NULL::bool AS does_equal
     , NULL::int =  NULL::int AS does_equal
     , NULL::text = NULL::text AS does_equal
     , ARRAY[NULL] = ARRAY[NULL] AS does_equal
     , ARRAY[NULL]::bool[] = ARRAY[NULL]::bool[] AS does_equal
     , ARRAY[NULL]::int[] = ARRAY[NULL]::int[] AS does_equal
     , ARRAY[NULL]::text[] = ARRAY[NULL]::text[] AS does_equal
;

Я понимаюпочему NULL = NULL равно NULL для примитивов, и я также думаю, что понимаю, почему сравнение составных типов даст истинное сравнение для поля в них, которое является нулевым с обеих сторон, в основном из-за оператора * =, который просматривает двоичное значениетип.Но в массивах, похоже, не используется оператор * =, и я пока не смог найти ничего, объясняющего это в моих поисках.

Ответы [ 2 ]

0 голосов
/ 04 февраля 2019

Это сложная история.

Вот что сказано в стандарте SQL (ISO / IEC 9075-2) в разделе «8.2.”:

Пусть XV и YV будут двумя значениями, представленнымиs X и Y соответственно.Результат:

<em>X</em> <comp op> <em>Y</em>

определяется следующим образом:
Случай:

  1. Если либо XV или YV - нулевое значение, тогда

    <em>X</em> <comp op> <em>Y</em>

    - Неизвестно.

  2. В противном случае,

    Case:

    1. Если объявленные типы XV и YV являются типами строк со степенью N , топусть X i , 1 (один) ≤ i N , обозначим aчьим значением и объявленным типом является значение i -ого поля XV , и пусть Y i обозначаетчье значение и объявленный тип соответствуют типу i -ого поля YV .
      Результат

      <em>X</em> <comp op> <em>Y</em>

      равенопределяется следующим образом:

      1. X = Y равно True тогда и только тогда, когда X i = Y i is True для всех i .
      2. X <<em> Y равно True тогда и только тогда, когда X i = Y i равно True для всех i <<em> n и X n = Y n для некоторых n .
      3. X = Y равно False тогда и только тогда, когда НЕТ ( X i = Y i ) равно True для некоторых i .
      4. X <<em> Y равно False тогда и только тогда, когда X = Y равно True или Y <<em> X is True .
      5. X Y - Неизвестно , если X Y не является ни Верным , ни Ложным .
    2. Если заявленные типы XV и YV - это типы массивов с кардинальными числами N1 и N2 соответственно, тогда пусть X i ,1 (один) ≤ i N1 , обозначаетчье значение и объявленный тип соответствуют типу i -го элемента XV , и пусть Y i обозначаетчьим значением и объявленным типом является значение i -го элемента YV .Результат

      <em>X</em> <comp op> <em>Y</em>

      определяется следующим образом:

      1. X = Y равен True , если N1 = 0 (ноль) и N2 = 0 (ноль).
      2. X = Y is True , если N1 = N2 и, для всех i , X i = Y i is True .
      3. X = Y is Неверно тогда и только тогда, когда N1 N2 или НЕ ( X i = Y i ) равно True , для некоторых i .
      4. X Y - Неизвестно , если X Y не является ни Верным , ни Ложным .

Тоэто довольно запутанно, например, я не вижу никакой спецификации, потому что сравнивать массивы с другими, кроме операторов равенства.

Стандарт также иногда противоречит сам себе.

Оператор *= существует только для record, не для массивов.Он работает почти так же, как =, но более эффективен, поскольку не «сбрасывает» значения, если их длина различна.

Лучше всего принять семантику такой, какая она есть.

Кажется, что PostgreSQL не следует стандарту в этом.

Сам по себе NULL сбивает с толку, NULL в композитах или массивах тем более.

0 голосов
/ 04 февраля 2019

Я не могу найти документацию по описанному вами поведению.Тем не менее, NULL s считаются равными для конструкторов записей и строк, и это объясняется в явном виде:

Спецификация SQL требует построчного сравнения для возврата NULL, если результат зависит от сравнения двух значений NULLили NULL и не NULL.,,,В других контекстах, где сравниваются два значения составного типа, два значения поля NULL считаются равными, а значение NULL считается большим, чем ненулевое значение.

Массив не является составным типом.Казалось бы, используется похожая логика.

...