Поведение NOT LIKE со значениями NULL
Я хочу получить все столбцы таблицы, кроме столбцов типа serial. Самый близкий запрос к этой проблеме, который я смог придумать:
SELECT column_name FROM information_schema.columns
WHERE table_name = 'table1' AND column_default NOT LIKE 'nextval%'
но проблема в том, что она также исключает / фильтрует строки, имеющие пустые значения для column_default.Я не знаю, почему поведение Postgres таково. Поэтому мне пришлось изменить свой запрос на что-то вроде этого:
SELECT column_name FROM information_schema.columns
WHERE table_name = 'table1'
AND ( column_default IS NULL OR column_default NOT LIKE 'nextval%')
любые лучшие предложения или обоснование этого приветствуются.
3 ответов
о NULL
'anything' NOT LIKE NULL
доходность NULL
, а не TRUE
.
И только TRUE
квалифицируется для выражений фильтра в WHERE
предложения.
большинство функций возвращают NULL
on NULL
input (есть исключения). Такова природа NULL
на любой правильная РСУБД.
если вы желаете один выражения мог бы использование:
AND (column_default LIKE 'nextval%') IS NOT TRUE;
это вряд ли короче или быстрее, хотя. подробности в руководстве.
правильный запрос
ваш запрос по-прежнему ненадежен. Только имя таблицы не является уникальным в базе данных Postgres, вам нужно указать имя схемы дополнительно или полагаться на текущее search_path
найти первый матч в это:
по теме:
SELECT column_name
FROM information_schema.columns
WHERE table_name = 'hstore1'
AND table_schema = 'public' -- your schema
AND (column_default IS NULL OR
column_default NOT LIKE 'nextval%');
лучше, но все же не пуленепробиваемый. По умолчанию столбец начиная с nextval не сделать serial
, пока нет. См.:
чтобы убедиться, проверьте, является ли используемая последовательность "собственностью" столбца с pg_get_serial_sequence(table_name, column_name)
.
я сам редко использую информационную схему. Эти медленные, раздутые представления гарантируют переносимость через основные версии-и направлены на переносимость к другим стандартн-уступчивым РСУБД. Но все равно слишком многое несовместимо. Oracle даже не реализует информационную схему (по состоянию на 2015 год).
кроме того, в информационной схеме отсутствуют полезные столбцы Postgres. В этом случае я мог бы запросить системные каталоги следующим образом:
SELECT *
FROM pg_catalog.pg_attribute a
WHERE attrelid = 'table1'::regclass
AND NOT attisdropped -- no dropped (dead) columns
AND attnum > 0 -- no system columns
AND NOT EXISTS (
SELECT FROM pg_catalog.pg_attrdef d
WHERE (d.adrelid, d.adnum) = (a.attrelid, a.attnum)
AND d.adsrc LIKE 'nextval%'
AND pg_get_serial_sequence(a.attrelid::regclass::text, a.attname) <> ''
);
быстрее и надежнее, но менее портативный.
в каталог
pg_attrdef
сохраняет значения столбца по умолчанию. Сеть информация о столбцах хранится вpg_attribute
(см. ниже). Только столбцы, которые явно указывают значение по умолчанию (когда таблица создано или добавлен столбец) будет иметь запись здесь.
'table1'::regclass
использует search_path
для разрешения имени, что позволяет избежать двусмысленности. Вы можете schema-квалифицировать имя для отмены:'myschema.table1'::regclass
.
по теме:
AND column_default NOT LIKE 'nextval%' OR column_default IS NULL
также можно написать
AND NOT column_default LIKE 'nextval%'
Я думаю, вы можете использовать:
SELECT column_name *FROM* information_schema.columns
WHERE table_name = 'table1'
AND ( nvl(column_default,0) *NOT LIKE* 'nextval%');