sql-server - 令人困惑的行为 - 使用向导创建的 SQL Server 信息架构和列

标签 sql-server database tsql information-schema database-metadata

编辑: 我尝试了这段代码,这是用户提到的一部分,它正确地返回了字段。

SELECT * FROM INFORMATION_SCHEMA.TABLES 
        JOIN INFORMATION_SCHEMA.COLUMNS on 
        INFORMATION_SCHEMA.TABLES.TABLE_NAME = 
        INFORMATION_SCHEMA.COLUMNS.TABLE_NAME
WHERE INFORMATION_SCHEMA.TABLES.TABLE_NAME = 'myTable'

前一个查询中的某些内容适用于某些数据库但不适用于其他数据库


编辑2:

我已尝试按照用户的建议设置 Profiler 跟踪以检查通过向导创建的列。显然,它使用相同的模式。

ALTER TABLE dbo.table1 ADD
field2 nchar(10) NULL

我正在使用 SQL Server 2014,并使用向导创建数据库,我的意思是,不是通过代码,而是通过使用 UI。

然后,我尝试获取有关其表列的元数据信息……但没有返回任何结果。我查询 INFORMATION_SCHEMA。

我试过对我通过代码创建的数据库使用相同的查询,它工作正常,它返回列及其值等。

我尝试在互联网上查找它,但似乎想不出适合此类情况的任何内容。我认为它与通过代码和通过 UI 创建的列有所不同有点奇怪。如果有人知道为什么会发生这样的事情,或者看起来很熟悉,我将不胜感激 :)

这是我用来检索列元数据的代码:

USE 'database'
SELECT infSch.TABLE_CATALOG,
       infSch.TABLE_NAME,
       sysCols.name,
       infSch.ORDINAL_POSITION,
       sysCols.is_nullable,
       infSch.DATA_TYPE,
       infSch.CHARACTER_MAXIMUM_LENGTH,
       sysCols.is_identity,
       IIF(infSchCons.CONSTRAINT_TYPE = 'PRIMARY KEY', 1, 0),
       IIF(infSchCons.CONSTRAINT_TYPE = 'FOREIGN KEY', 1, 0),
       IIF(infSchCons.CONSTRAINT_TYPE = 'UNIQUE', 1, 0),
       IIF(infSchCons.CONSTRAINT_TYPE = 'CHECK', 1, 0)
FROM sys.columns as sysCols 
RIGHT JOIN INFORMATION_SCHEMA.COLUMNS as infSch on sysCols.name = 
     infSch.COLUMN_NAME
RIGHT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS as infSchCons on 
     infSch.TABLE_NAME = infSchCons.TABLE_NAME

结果:

  • 如果表和列是由代码创建的 --> 它返回给定数据库的所有列及其元数据

  • 如果表和列是使用 UI 和窗口创建的 --> 它不返回任何内容,只是一组空结果

最佳答案

右连接改变了查询的性质,它们总是可以通过颠倒表的顺序来重写。避免正确的连接....试试这个:

SELECT infSch.TABLE_CATALOG,
       infSch.TABLE_NAME,
       sysCols.name,
       infSch.ORDINAL_POSITION,
       sysCols.is_nullable,
       infSch.DATA_TYPE,
       infSch.CHARACTER_MAXIMUM_LENGTH,
       sysCols.is_identity,
       IIF(infSchCons.CONSTRAINT_TYPE = 'PRIMARY KEY', 1, 0),
       IIF(infSchCons.CONSTRAINT_TYPE = 'FOREIGN KEY', 1, 0),
       IIF(infSchCons.CONSTRAINT_TYPE = 'UNIQUE', 1, 0),
       IIF(infSchCons.CONSTRAINT_TYPE = 'CHECK', 1, 0)
FROM sys.columns as sysCols 
LEFT JOIN INFORMATION_SCHEMA.COLUMNS as infSch on sysCols.name = 
     infSch.COLUMN_NAME
LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS as infSchCons on 
     infSch.TABLE_NAME = infSchCons.TABLE_NAME

该查询不会将结果限制为仅存在约束的结果。

尝试比较这些:

select count(*) from (

    SELECT
        infSchCons.*
    FROM sys.columns as sysCols 
    right JOIN INFORMATION_SCHEMA.COLUMNS as infSch on sysCols.name = infSch.COLUMN_NAME
    right JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS as infSchCons on infSch.TABLE_NAME = infSchCons.TABLE_NAME

    ) x
;

select count(*) from (

    SELECT
        infSchCons.*
    FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS infSchCons
    left JOIN INFORMATION_SCHEMA.COLUMNS AS infSch ON infSchCons.TABLE_NAME = infSch.TABLE_NAME
    left JOIN sys.columns AS sysCols ON infSch.COLUMN_NAME = sysCols.name

    ) x
;

最后一个查询是对原始 from 子句的重写,在这里(在我看来)更容易看出您必须对要返回的任何行具有约束。


编辑

问题询问为什么特定查询在某些数据库中不起作用。

该查询使用 RIGHT OUTER JOINS

由于连接类型的操作方式,它改变了表的优先级——这可能会造成混淆

因为所有正确的连接都可以“反转”,所以当您执行等效查询(对原始查询)时,有一个这样的 from 子句:

FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS infSchCons
left JOIN INFORMATION_SCHEMA.COLUMNS AS infSch ON infSchCons.TABLE_NAME = infSch.TABLE_NAME
left JOIN sys.columns AS sysCols ON infSch.COLUMN_NAME = sysCols.name

所以优先级最高的表是INFORMATION_SCHEMA.TABLE_CONSTRAINTS如果该表中没有行,查询将不会返回任何数据

在对问题的第二次编辑中,有一个有效的查询:

SELECT
    *
FROM INFORMATION_SCHEMA.TABLES
JOIN INFORMATION_SCHEMA.COLUMNS ON INFORMATION_SCHEMA.TABLES.TABLE_NAME =
    INFORMATION_SCHEMA.COLUMNS.TABLE_NAME
WHERE INFORMATION_SCHEMA.TABLES.TABLE_NAME = 'myTable'

并且:这个“有效”是因为具有最高优先级的表是 INFORMATION_SCHEMA.TABLES,几乎可以保证其中有行。

因此,原始查询使用了错误的最高优先级表,由于正确的连接而被掩盖了。有效的查询使用一个合理的表作为其基表,并且不使用右连接。

关于sql-server - 令人困惑的行为 - 使用向导创建的 SQL Server 信息架构和列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53696807/

相关文章:

SQL:如何选择具有重复项的唯一行

mysql - SQL查询使数据聚合变得困难

sql - T-SQL-获取具有相同B组的所有As的列表

sql - 如何从 SQL 查询设置变量?

c# - 使用 C# 将 Excel 导入 SQL Server 时出现 "The given ColumnMapping does not match up with any column in the source or destination"

mysql - 数据库规范化: relationship based on join

php - 插入排名的最佳方式(带有php的SQL数据库)

sql - 在 SQL 中查找租用每辆车的所有用户

ruby-on-rails - “拆分”ActiveRecord 集合

sql - 删除表中多个重复行