SQL Anywhere 查询挖掘模式结构

SQL Anywhere query to dig schema structure

我正在尝试创建一个 SQL 查询来执行以下操作:

  1. Select 架构中的所有 tables
  2. Select 来自 table
  3. 的所有列
  4. Select 列类型(char、int、tinyint 等)
  5. Select 列索引类型或 NULL(索引类型为 FK 或 PK)
  6. 如果有外键索引,select主table

此数据应放入 XML 文件中。请注意,这是在 SQL Anywhere.

XML 文件的代码很容易写,但我卡在查询中。

我目前有一个查询可以 select 所有列,它们的 table 和它们的数据类型。

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%';

当前 returns 例如:

[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 有系统 table,例如:SYSFKEYSYSIDXSYSIDXCOL,但我不知道我是怎么做到的将其实现到我自己的查询中。

我在互联网上四处寻找,可以找到很多其他 SQL 服务的示例,但是 none 对于 SQL 任何地方。

我真的需要一些帮助。

更新 1:
所以我发现 table SYSFKEY 有一些有趣的专栏。

这里的primary_table_id好像是指国外的table.

table SYSIDX 也有列

我希望我能以某种方式将所有这些联系在一起

更新二: 所以我写了一个新的查询,实际上效果出奇的好。我以为我修复了它,直到我 运行 遇到一些奇怪的事情。

当前查询是这样的:

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%';

而这实际上 returns 很多有用的信息!但是奇怪的事情发生了。

一个table中有多个主键。也许这就是创作者设计的方式,每个字段在一起就是主键,但对我来说似乎很奇怪。

也有多个重复项(多行和以前存在的列)

具有多个 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 索引,对吧?或者可能查询卡住了,只是在每个结果中不断转储相同的信息?

所以我花了很多时间,但我终于想出了一个办法。我正在分享这个答案,以防其他人遇到这个问题。

答案并不完美,即使使用 LIST() 函数,仍会产生一些重复的行。这只有在存在中间 table 时才会成为问题。我仍在尝试解决这个问题,但大多数问题都可以通过简单的 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;

此查询将:

  • Select 列的 table 名称为 table_name
  • Select 当前列名称为 column_name
  • Select列的默认值为default_value
  • Select 列数据类型为 base_type_str(考虑 int、bool、date 等)
  • 大小写 index_category 列,其中 1 表示该列是 PK,2 表示 FK,其他任何内容都将 return as '' as index_type
  • FK 引用的 table 名称为 foreign_table

where 子句确实特定于我的数据库模式,因为它过滤所有 tab%(tables)和 vw%(视图),但这可以是任何东西。尽管在不指定时也会为您提供所有系统 tables。