我inheritance了一个有400个表的数据库,并且只有150个外键约束被注册。 知道我对应用程序做了些什么,然后看着表格列,很容易就可以知道应该有更多。
如果我开始添加缺less的FKs,恐怕现在的应用软件会中断,因为开发者可能会依赖这个“自由”,但是解决问题的第一步是找出缺失的FK列表我们可以评估他们作为一个团队。
更糟糕的是,引用列不共享命名约定。
这些关系被非正式地编码到数百个即席查询和存储过程中,所以我希望通过编程的方式来parsing这些文件,寻找实际表(而不是表variables等)之间的连接。
我在这种方法中预见到的挑战是:换行符,可选别名和表格提示,别名parsing。
function强大的SQLparsing器可以自动分析数百个临时查询和存储过程,并且可以从SQLparsing器生成的查询parsing树中轻松findvariables表/列的关系。
这是示例:
SELECT a.ASSMT_NO, b.LINK_PARAM, c.EXPL AS LINK_PG, (SELECT count() FROM GRAASPST t WHERE t.ASSMT_NO = a.ASSMT_NO AND t.ROLE != '02') AS PSN_CNT, (SELECT count() FROM GRAASPST t WHERE t.ASSMT_NO = a.ASSMT_NO AND t.ROLE != '02' AND ASSMT_FIN_YN = 'Y') AS PSN_FIN_CNT, (SELECT Avg(assmt_pts) FROM GRAASSMT t WHERE t.ASSMT_NO = a.ASSMT_NO AND t.ASSMT_TGT_SEQ_NO = a.ASSMT_TGT_SEQ_NO) AS ASSMT_PTS_AVG, a.ASSMT_RES, a.ASSMT_RPT_SUB_TITLE FROM GRAASTAT a JOIN GRAASRET b ON b.DELIB_REQ_NO = a.DELIB_REQ_NO JOIN GRTCODDT c ON c.DIV_CD = 'GR013' AND c.CD = b.DELIB_SLCT JOIN CMUSERMT d ON d.USERID = a.REGID WHERE a.ASSMT_NO = :ASSMT_NO ORDER BY a.ASSMT_TGT_SEQ_NO
分析完这个查询后,你可能会得到这样的结果:
JoinTable1 JoinColumn1 JoinTable2 JoinColumn2 GRAASRET DELIB_REQ_NO GRAASTAT DELIB_REQ_NO GRTCODDT CD GRAASRET DELIB_SLCT CMUSERMT USERID GRAASTAT REGID GRAASPST ASSMT_NO GRAASTAT ASSMT_NO GRAASSMT ASSMT_NO GRAASTAT ASSMT_NO GRAASSMT ASSMT_TGT_SEQ_NO GRAASTAT ASSMT_TGT_SEQ_NO
你可以查看这个演示了解详细信息。
我感到你的痛苦。
免费的SQLsearch SSMS插件可能会对您有所帮助。
一般来说,是的,正则expression式可以处理这个问题,但是你应该意识到在试图召唤正则expression式魔法的时候,回报递减点。 在映射出关系的同时,您可能会更好地审查和search代码。
SQL Search可能会让你更容易。
这是我想出来的。 此查询查找不是表的主键的外键类列(int,bigint,guid),它们当前没有使用外键约束进行注册。 当然,我得到了一些sorting顺序和数量列,但是与parsingSQL脚本相比,它确实缩小了列表的范围。
WITH ExistingFKCs AS ( SELECT CU.TABLE_NAME, -- Referencing Table CU.COLUMN_NAME -- Referencing Column FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS C JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE CU ON C.CONSTRAINT_NAME = CU.CONSTRAINT_NAME ) SELECT T.TABLE_NAME AS [Table Name], COL.COLUMN_NAME AS [Column Name] FROM INFORMATION_SCHEMA.TABLES T JOIN INFORMATION_SCHEMA.COLUMNS COL ON T.TABLE_TYPE = 'BASE TABLE' AND COL.TABLE_NAME = T.TABLE_NAME LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS PKC ON PKC.CONSTRAINT_TYPE = 'Primary Key' AND PKC.TABLE_NAME = COL.TABLE_NAME LEFT JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE PKCU ON PKCU.TABLE_NAME = PKC.TABLE_NAME AND PKCU.CONSTRAINT_NAME = PKC.CONSTRAINT_NAME AND PKCU.COLUMN_NAME = COL.COLUMN_NAME LEFT JOIN ExistingFKCs EFKS ON EFKS.TABLE_NAME = COL.TABLE_NAME AND EFKS.COLUMN_NAME = COL.COLUMN_NAME WHERE PKCU.COLUMN_NAME IS NULL AND EFKS.COLUMN_NAME IS NOT NULL AND COL.DATA_TYPE IN ('int', 'bigint','uniqueidentifier') ORDER BY T.TABLE_NAME, COL.COLUMN_NAME