1

假设我有从数据库中读取的 POCO 实体,并且它们每个都有“ID”作为它们的主键列名。

如果从多个具有别名 a 和 b 的表或子查询中进行select a.*, b.* from a, b选择,则所选列将包括两个 ID 列(a.ID 和 b.ID),但源表/子查询别名会丢失。我想知道是否有办法为任意选择查询的输出列的源保留或动态获取这样的顶级别名。

我知道我可以更改输出列名称或按序号访问它们,但我需要按原始名称 + 源表/子查询的别名来访问列,例如“a.ID”和“b.ID”。

默认情况下,SqlDataReader 似乎不保留列的基表信息,并且从不保留别名信息。

有没有办法区分 SqlDataReader 中的这些列或让它保留每列的源表/子查询别名?

这里问了一个类似的问题:Differentialing between 2 SQL column names with same name in a C# SqlConnection,但答案是给列唯一的别名,这不是我想要的。我希望能够为表使用别名,同时保留原始列名。

在这里询问:如何从 SqlDataReader 获取列的表名并在此处回答:https ://stackoverflow.com/a/3111208/88409 ,但他们提到它不会返回表别名,只会返回原始基表,其中对带有别名的子查询没用。

更新:似乎无法完成。与一个问题相关的问题之一说它没有得到回答,但实际上已经得到了回答:Getting table schema from a query 似乎别名就像查询的“源代码”,它们在编译/优化过程中被剥离,所以最后只剩下真正的表格信息。

4

1 回答 1

1

正如我所怀疑的那样,另一个人是错的,所以我要回答我自己的问题。

在 SQL Server 2012(可能还有更早的版本)中,我发现如果我调用 'set showplan_xml on;' 在任意查询上,例如:

select * from (select * from Lessons a) a inner join (select * from LessonTypes b) b on a.LessonTypeID = b.ID;

返回的 XML 包括以下内容作为其第一级/顶级 OutputList,它清楚地显示了所有列,不仅显示了它们的源表,还显示了它们的源子查询的别名。

<OutputList>
    <ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[Lessons]" Alias="[a]" Column="ID"/>
    <ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[Lessons]" Alias="[a]" Column="Name"/>
    <ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[Lessons]" Alias="[a]" Column="Description"/>
    <ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[Lessons]" Alias="[a]" Column="Enabled"/>
    <ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[Lessons]" Alias="[a]" Column="LessonTypeID"/>
    <ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[LessonTypes]" Alias="[b]" Column="ID"/>
    <ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[LessonTypes]" Alias="[b]" Column="Name"/>
    <ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[LessonTypes]" Alias="[b]" Column="Description"/>
 </OutputList>

因此,在我的数据库 API 中,由于我将所有查询字符串整齐地存储在字典中,我实际上可以在应用程序启动时执行缓存预热,在 xml_showplan 上运行它们,解析 XML 顶级输出列,然后具有表别名和列名与其输出序号的完整映射。

实际上,我在这里使用了一个小技巧。它实际上不是子查询的别名,而是基表的别名。如果您未在基表中包含别名,则 XML 中不存在 Alias 属性。但是,确保每次引用实际表时都给它一个别名是非常简单的,这应该会导致它输出到 XML,然后就可以了。

只是为了说明这一点,即使在查询中将表连接到自身时,别名也会保持不变,例如:

select * from Lessons a, Lessons b, Lessons c,产生:

<OutputList>
    <ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[Lessons]" Alias="[a]" Column="ID"/>
    <ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[Lessons]" Alias="[a]" Column="Name"/>
    <ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[Lessons]" Alias="[a]" Column="Description"/>
    <ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[Lessons]" Alias="[a]" Column="Enabled"/>
    <ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[Lessons]" Alias="[a]" Column="LessonTypeID"/>
    <ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[Lessons]" Alias="[b]" Column="ID"/>
    <ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[Lessons]" Alias="[b]" Column="Name"/>
    <ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[Lessons]" Alias="[b]" Column="Description"/>
    <ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[Lessons]" Alias="[b]" Column="Enabled"/>
    <ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[Lessons]" Alias="[b]" Column="LessonTypeID"/>
    <ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[Lessons]" Alias="[c]" Column="ID"/>
    <ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[Lessons]" Alias="[c]" Column="Name"/>
    <ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[Lessons]" Alias="[c]" Column="Description"/>
    <ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[Lessons]" Alias="[c]" Column="Enabled"/>
    <ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[Lessons]" Alias="[c]" Column="LessonTypeID"/>
</OutputList>

如您所见,别名实际上是完整且可检索的。

于 2013-10-23T08:54:25.503 回答