SQLite: обрабатывать несуществующий столбец как NULL - PullRequest
1 голос
/ 27 февраля 2020

У меня такой запрос (упрощенный и анонимный):

SELECT
    Department.id,
    Department.name,
    Department.manager_id,
    Employee.name AS manager_name
FROM
    Department
LEFT OUTER JOIN Employee
    ON Department.manager_id = Employee.id;

Поле Department.manager_id может быть NULL. Если это не-NULL, то он гарантированно будет действительным id для ровно одной строки в таблице Employee, поэтому OUTER JOIN существует только для строк в таблице Department, где он находится NULL.

Вот проблема: старые экземпляры базы данных вообще не имеют этого столбца Department.manager_id. В этих случаях я хотел бы, чтобы запрос действовал так, как если бы поле действительно существовало, но всегда было NULL, поэтому, например, поле manager_name возвращается как NULL. Если бы в запросе использовалась только таблица Department, то я мог бы просто использовать SELECT * и проверить столбец в моем приложении, но JOIN, кажется, делает это невозможным. Я бы предпочел не изменять базу данных, частично, чтобы я мог загрузить базу данных в режиме только для чтения. Можно ли это сделать просто путем умной настройки запроса?

Ответы [ 2 ]

1 голос
/ 28 февраля 2020

Для полноты приведем ответ, который не требует объединения обеих возможных схем в один запрос (но все же не требует, чтобы вы фактически выполняли миграцию схемы):

Проверьте версию схемы и используйте его, чтобы определить, какой запрос SELECT отправить (т. е. с или без столбца manager_id и JOIN) в качестве отдельного шага. Вот несколько возможностей определить версию схемы:

  • Идеальная ситуация заключается в том, что вы уже отслеживаете схему, назначая номера версий для схемы и записывая их в базу данных. Обычно это делается с помощью:
    • user_version pragma .
    • Таблица с именем «Схема» или аналогичная с одной строкой, содержащей номер версии схемы.
  • Вы можете напрямую определить, присутствует ли столбец в таблице. Две возможности:
    • Используйте table_info pragma , чтобы определить список столбцов в таблице.
    • Используйте простое SELECT * FROM Table LIMIT 1 и посмотрите, какие столбцы возвращаются (это, вероятно, лучше, так как он не зависит от ядра базы данных).
0 голосов
/ 28 февраля 2020

Кажется, что это работает:

SELECT
    Dept.id,
    Dept.name,
    Dept.manager_id,
    Employee.name AS manager_name
FROM
    (SELECT *, NULL AS manager_id FROM Department) AS Dept
LEFT OUTER JOIN Employee
    ON Dept.manager_id = Employee.id;

Если столбец manager_id присутствует в Department, тогда он используется для объединения, тогда как если нет, то Dept.manager_id и Employee.name оба равны NULL.

Если я поменяю местами порядок столбцов в подзапросе:

(SELECT NULL AS manager_id, * FROM Department) AS Dept

, тогда Dept.manager_id и Employee.name равны NULL, даже если существует столбец Department.manager_id, так что, похоже, Dept.manager_id относится к столбцу first в подзапросе Dept с таким именем. Было бы хорошо найти в документации по SQLite ссылку, в которой говорится, что это поведение гарантировано (или явно сказано, что это не так), но я ничего не могу найти (например, в SELECT или выражение страницы).

Я не пробовал этого с другими системами баз данных, поэтому я не знаю, будет ли он работать с чем-либо, кроме SQLite.

...