令人困惑的行为 - SQL 服务器信息架构和使用向导创建的列
Confusing behaviour - SQL Server Information Schema and columns created by using the wizard
编辑:
我尝试了这段代码,这是用户提到的一部分,它 returns 字段正确。
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:
我已经按照用户的建议尝试设置探查器跟踪以检查通过向导创建的列。显然,它使用相同的模式。
ALTER TABLE dbo.table1 ADD
field2 nchar(10) NULL
我正在使用 SQL Server 2014,并使用向导创建数据库,我的意思是,不是通过代码,而是通过使用 UI.
然后,我尝试获取关于他们的 table 列的元数据信息.. 但没有返回任何结果。我查询INFORMATION_SCHEMA.
我试过对我通过代码创建的数据库使用相同的查询,它工作正常,它 returns 列及其值等
我试过在互联网上查找它,但似乎想不出适合这些情况的任何东西。我认为它与代码创建的列和通过 UI. =14=]
这是我用来检索列元数据的代码:
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
结果:
如果 table 和列是由代码创建的 --> 它 returns 给定数据库的所有列及其元数据
如果 table 和列是使用 UI 和 windows 创建的 --> 它 returns 什么都没有,只是一个空集结果
右连接改变了查询的性质,它们总是可以通过颠倒 table 的顺序来重写。避免正确的连接....试试这个:
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 子句的重写,在这里(在我看来)更容易看出您必须对要 returned 的任何行设置约束。
编辑
问题询问为什么特定查询在某些数据库中不起作用。
该查询使用 RIGHT OUTER JOINS
由于 join 类型的操作方式,它改变了 tables 的优先级——这可能会造成混淆
因为所有正确的联接都可以是 "reversed",当您执行等效查询(对原始查询)时,有一个这样的 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
所以优先级最高的table是INFORMATION_SCHEMA.TABLE_CONSTRAINTS
,如果那个table里面没有行,查询就不会return任何数据.
在对问题的第二次编辑中,有一个有效的查询:
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'
并且:这个"works"因为优先级最高的table是INFORMATION_SCHEMA.TABLES
,几乎可以保证其中有行。
因此,原始查询使用了错误的最高优先级 table,由于正确的连接而被遮盖了。有效的查询使用合理的 table 作为基础 table,并且不使用右连接。
编辑: 我尝试了这段代码,这是用户提到的一部分,它 returns 字段正确。
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:
我已经按照用户的建议尝试设置探查器跟踪以检查通过向导创建的列。显然,它使用相同的模式。
ALTER TABLE dbo.table1 ADD
field2 nchar(10) NULL
我正在使用 SQL Server 2014,并使用向导创建数据库,我的意思是,不是通过代码,而是通过使用 UI.
然后,我尝试获取关于他们的 table 列的元数据信息.. 但没有返回任何结果。我查询INFORMATION_SCHEMA.
我试过对我通过代码创建的数据库使用相同的查询,它工作正常,它 returns 列及其值等
我试过在互联网上查找它,但似乎想不出适合这些情况的任何东西。我认为它与代码创建的列和通过 UI. =14=]
这是我用来检索列元数据的代码:
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
结果:
如果 table 和列是由代码创建的 --> 它 returns 给定数据库的所有列及其元数据
如果 table 和列是使用 UI 和 windows 创建的 --> 它 returns 什么都没有,只是一个空集结果
右连接改变了查询的性质,它们总是可以通过颠倒 table 的顺序来重写。避免正确的连接....试试这个:
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 子句的重写,在这里(在我看来)更容易看出您必须对要 returned 的任何行设置约束。
编辑
问题询问为什么特定查询在某些数据库中不起作用。
该查询使用 RIGHT OUTER JOINS
由于 join 类型的操作方式,它改变了 tables 的优先级——这可能会造成混淆
因为所有正确的联接都可以是 "reversed",当您执行等效查询(对原始查询)时,有一个这样的 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
所以优先级最高的table是INFORMATION_SCHEMA.TABLE_CONSTRAINTS
,如果那个table里面没有行,查询就不会return任何数据.
在对问题的第二次编辑中,有一个有效的查询:
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'
并且:这个"works"因为优先级最高的table是INFORMATION_SCHEMA.TABLES
,几乎可以保证其中有行。
因此,原始查询使用了错误的最高优先级 table,由于正确的连接而被遮盖了。有效的查询使用合理的 table 作为基础 table,并且不使用右连接。