Запрос SQL Anywhere для изучения структуры схемы

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

  1. Выбрать все таблицы в схеме
  2. Выделить все столбцы из таблицы
  3. Выберите тип столбца (char, int, tinyint и т. д.)
  4. Выберите тип индекса столбцов или NULL (тип индекса FK или PK).
  5. Если есть индекс внешнего ключа, выберите основную таблицу

Затем эти данные должны быть помещены в файл XML. Обратите внимание, что это в SQL Anywhere.

Код для файла XML легко написать, но я застрял на запросе.

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

SELECT t.table_name AS table_name, 
       c.column_name AS column_name, 
       c.base_type_str 
FROM sys.systabcol c 
    INNER JOIN sys.systab t 
        ON t.table_id = c.table_id 
WHERE t.table_type_str = 'BASE' 
    AND t.table_name NOT LIKE 'ISYS%';

который в настоящее время возвращает, например:

[6585]=>
    array(3) {
      ["table_name"]=>
      string(17) "my_table"
      ["column_name"]=>
      string(6) "number"
      ["base_type_str"]=>
      string(7) "integer"
    }

Мой желаемый результат будет (например):

[6585]=>
    array(3) {
      ["table_name"]=>
      string(17) "my_table"
      ["column_name"]=>
      string(6) "number"
      ["base_type_str"]=>
      string(7) "integer" // or other types
      ["index_type"]=>
      string(7) "FK" // or "PK" or "NULL"
      ["primary_table"]=>
      string(7) "some_other_table" // or "NULL"
    }

Я знаю, что в SQL Anywhere есть такие системные таблицы, как: SYSFKEY, SYSIDX и SYSIDXCOL, но я понятия не имею, как реализовать это в своем собственном запросе.

Я поискал в Интернете и могу найти множество примеров для других служб SQL, но ни одного для SQL Anywhere.

Мне действительно не помешала бы помощь в этом.

Обновление 1:
Итак, я выяснил, что в таблице SYSFKEY есть несколько интересных столбцов.

  • ид_иностранной_таблицы
  • иностранный_индекс_ид
  • идентификатор основной_таблицы

где, кажется, что primary_table_id относится к внешней таблице.

Также в таблице SYSIDX есть столбцы

  • table_id
  • index_id

Надеюсь, я смогу как-то связать все это воедино

Обновление 2: Итак, я написал новый запрос, который на самом деле работает на удивление хорошо. Я думал, что исправил это, пока не столкнулся с некоторыми странностями.

На данный момент запрос такой:

SELECT tab.table_name as table_name,
       col.column_name as column_name,
       col.`default` as default_value,
       col.base_type_str,
       (
           case idx.index_category
           when 1 then 'PK'
           when 2 then 'FK'
           else 'NULL'
           end
       ) as index_type,
       tab1.table_name as foreign_table
FROM sys.systabcol col
    INNER JOIN sys.systab tab
        ON tab.table_id = col.table_id
    LEFT JOIN sys.sysidx idx
        ON idx.table_id = col.table_id
    LEFT JOIN sys.sysidxcol idxc
        ON idxc.table_id = idx.table_id AND idxc.index_id = idx.index_id
    LEFT JOIN sys.sysfkey fk
        ON fk.foreign_table_id = idx.table_id AND fk.foreign_index_id = idx.index_id
    LEFT JOIN sys.systab tab1
        ON tab1.table_id = fk.primary_table_id
WHERE tab.table_name LIKE 'tab%' OR tab.table_name LIKE 'vw%';

И это на самом деле возвращает много полезной информации! Но происходит что-то странное.

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

Также есть несколько дубликатов (несколько строк со столбцами, которые были там раньше)

Example with multiple PK:

        table, th, td {
            border: 1px solid black;
            border-collapse: collapse;
        }
    
<table>
    <thead>
    <tr>
        <th colspan="4">tabMobilinkTabellen</th>
    </tr>
    </thead>
    <tbody>
    <tr><th>Key</th><th>Column</th><th>Type</th><th>Default</th></tr><tr><td>PK</td><td>MltGid</td><td>integer</td><td>autoincrement</td></tr><tr><td>PK</td><td>MltLastModified</td><td>timestamp</td><td>timestamp</td></tr><tr><td>PK</td><td>MltTablename</td><td>nchar(128)</td><td>''</td></tr>    </tbody>
</table>

Пример с несколькими индексами:

        table, th, td {
            border: 1px solid black;
            border-collapse: collapse;
        }
    
<table>
    <thead>
    <tr>
        <th colspan="4">tabAanhef</th>
    </tr>
    </thead>
    <tbody>
    <tr><th>Key</th><th>Column</th><th>Type</th><th>Default</th></tr><tr><td><a href="?table=tabTaal">FK</a></td><td>AanhefGid</td><td>integer</td><td>autoincrement</td></tr><tr><td></td><td>AanhefGid</td><td>integer</td><td>autoincrement</td></tr><tr><td></td><td>AanhefGid</td><td>integer</td><td>autoincrement</td></tr><tr><td>PK</td><td>AanhefGid</td><td>integer</td><td>autoincrement</td></tr><tr><td><a href="?table=tabTaal">FK</a></td><td>AanhefTaalGid</td><td>integer</td><td></td></tr><tr><td></td><td>AanhefTaalGid</td><td>integer</td><td></td></tr><tr><td></td><td>AanhefTaalGid</td><td>integer</td><td></td></tr><tr><td>PK</td><td>AanhefTaalGid</td><td>integer</td><td></td></tr><tr><td><a href="?table=tabTaal">FK</a></td><td>GeslachtAanhef</td><td>smallint</td><td>0</td></tr><tr><td></td><td>GeslachtAanhef</td><td>smallint</td><td>0</td></tr><tr><td></td><td>GeslachtAanhef</td><td>smallint</td><td>0</td></tr><tr><td>PK</td><td>GeslachtAanhef</td><td>smallint</td><td>0</td></tr><tr><td><a href="?table=tabTaal">FK</a></td><td>TekstAanhef</td><td>nchar(40)</td><td>''</td></tr><tr><td></td><td>TekstAanhef</td><td>nchar(40)</td><td>''</td></tr><tr><td></td><td>TekstAanhef</td><td>nchar(40)</td><td>''</td></tr><tr><td>PK</td><td>TekstAanhef</td><td>nchar(40)</td><td>''</td></tr><tr><td><a href="?table=tabTaal">FK</a></td><td>TekstAdres</td><td>nchar(40)</td><td>''</td></tr><tr><td></td><td>TekstAdres</td><td>nchar(40)</td><td>''</td></tr><tr><td></td><td>TekstAdres</td><td>nchar(40)</td><td>''</td></tr><tr><td>PK</td><td>TekstAdres</td><td>nchar(40)</td><td>''</td></tr><tr><td><a href="?table=tabTaal">FK</a></td><td>TekstBrief</td><td>nchar(40)</td><td>''</td></tr><tr><td></td><td>TekstBrief</td><td>nchar(40)</td><td>''</td></tr><tr><td></td><td>TekstBrief</td><td>nchar(40)</td><td>''</td></tr><tr><td>PK</td><td>TekstBrief</td><td>nchar(40)</td><td>''</td></tr>    </tbody>
</table>

Возможно, мне следует объединить их вместе, но все же странно, что в одном столбце несколько индексов FK, верно? Или, возможно, запрос застревает и продолжает выдавать одну и ту же информацию в каждом результате?


person Tim    schedule 24.02.2021    source источник


Ответы (1)


Так что это заняло у меня много времени, но я, наконец, нашел способ сделать это. Я делюсь этим ответом на случай, если кто-то еще столкнется с этим.

Ответ не идеален и все равно будет создавать повторяющиеся строки, даже с функцией LIST(). Это становится проблемой только при наличии промежуточной таблицы. Я все еще пытаюсь понять это, но большинство проблем можно отфильтровать с помощью простого PHP (или вашего предпочтительного языка).

Мой последний запрос на данный момент:

SELECT tab.table_name as table_name,
       col.column_name as column_name,
       col.`default` as default_value,
       col.base_type_str,
       LIST(
           case idx.index_category
           when 1 then 'PK'
           when 2 then 'FK'
           end
       ) as index_type,
       tab1.table_name as foreign_table
FROM sys.systabcol col
    LEFT JOIN sys.sysidxcol idxc
        ON idxc.table_id = col.table_id AND idxc.column_id = col.column_id
    INNER JOIN sys.systab tab
        ON col.table_id = tab.table_id
    LEFT JOIN sys.sysidx idx
        ON idx.table_id = idxc.table_id AND idx.index_id = idxc.index_id
    LEFT JOIN sys.sysfkey fk
        ON fk.foreign_table_id = idx.table_id AND fk.foreign_index_id = idx.index_id
    LEFT JOIN sys.systab tab1
        ON tab1.table_id = fk.primary_table_id
WHERE tab.table_name LIKE 'tab%' OR tab.table_name LIKE 'vw%' GROUP BY tab.table_name, col.column_name, col.`default`, col.base_type_str, tab1.table_name ORDER BY index_type DESC;

Этот запрос будет:

  • Выберите имя таблицы столбца как table_name
  • Выберите текущее имя столбца как column_name
  • Выберите значение столбца по умолчанию как default_value
  • Выберите тип данных столбца как base_type_str (подумайте о int, bool, date и т. д.)
  • Укажите столбец index_category, где 1 означает, что столбец является PK, 2 — FK, а все остальное будет возвращено как '' as index_type
  • Имя таблицы, на которую ссылается FK, как foreign_table

Предложение where действительно специфично для моей схемы базы данных, поскольку оно фильтрует все tab% (таблицы) и vw% (представления), но это может быть что угодно. Хотя, если это не указать, вы также получите все системные таблицы.

person Tim    schedule 03.03.2021