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 有系统表,例如:SYSFKEYSYSIDXSYSIdxcOL,但我不知道如何将其实现到我自己的查询中。>

我在互联网上环顾四周,我可以找到很多其他 sql 服务的示例,但没有 用于 sql Anywhere。

我真的可以在这方面寻求一些帮助。

更新 1:
所以我发现表 SYSFKEY 有一些有趣的列。

  • foreign_table_id
  • foreign_index_id
  • primary_table_id

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

这实际上返回了很多有用的信息!但奇怪的事情正在发生。

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

还有多个重复项(多行,其中的列之前已经存在)

具有多个 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,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() 函数,仍然会产生一些重复的行。这仅在存在中间表时才会成为问题。我仍在尝试解决这个问题,但大多数问题都可以通过简单的 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`,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%(视图),但这可以是任何东西。虽然不指定时也会为您提供所有系统表。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...