根据MSDN,SqlDataReader.GetSchemaTable
返回执行查询的列元数据.我想知道是否有一个类似的方法将给出给定查询的表元数据?我的意思是涉及哪些表以及它所拥有的别名.
在我的应用程序中,我得到了查询,我需要以where
编程方式附加该子句.使用GetSchemaTable()
,我可以获取列元数据及其所属的表.但即使表有别名,它仍然返回真正的表名.有没有办法获取该表的别名?
以下代码显示了获取列元数据.
const string connectionString = "your_connection_string"; string sql = "select c.id as s,c.firstname from contact as c"; using(SqlConnection connection = new SqlConnection(connectionString)) using(SqlCommand command = new SqlCommand(sql, connection)) { connection.Open(); SqlDataReader reader = command.ExecuteReader(CommandBehavior.KeyInfo); DataTable schema = reader.GetSchemaTable(); foreach (DataRow row in schema.Rows) { foreach (DataColumn column in schema.Columns) { Console.WriteLine(column.ColumnName + " = " + row[column]); } Console.WriteLine("----------------------------------------"); } Console.Read(); }
这将正确地提供列的详细信息.但是当我看到BaseTableName
列时Id
,它给出的contact
不是别名c
.有没有办法从上面的查询中获取表模式和别名?
任何帮助都会很棒!
编辑
虽然我可以使用Rob建议的执行计划,但我会欣赏任何其他简单的方法.
回答tomekszpakowicz提出的问题
您(或您的应用程序)是否有问题的查询来源?在这种情况下,您应该知道别名.
我不是查询的作者.我们有一个用户可以输入查询的系统.我们使用上面解释的方法从中构建列.这些细节将被保留,另一个用户可以像添加新标准一样使用它.因此,我们需要根据我们的信息动态构建SQL.因此,当列具有别名并且我们没有获得别名时,则构造的where子句将无效.
谢谢
简短的回答
这不行.根据设计,您无法从结果模式中获取表别名.并且您不能依赖于能够从查询执行计划中获取它们.
答案很长
当您获得SQL查询的结果时,该查询已经被解析,验证,优化,编译成一些内部表示并执行.别名是查询的"源代码"的一部分,通常在步骤1和2的某处丢失.
在执行查询之后,唯一可以看作表的东西是a)真实的物理表和b)返回的数据看作单个匿名表.可以转换或完全优化之间的所有内容.
如果要求DBMS保留别名,则实际上不可能优化复杂查询.
可能的解决方案
我建议重述一个问题:
您(或您的应用程序)是否有问题的查询来源?在这种情况下,您应该知道别名.
如果你得到别人提供的查询......那么......这取决于你为什么要添加原因.
在最坏的情况下,您必须自己解析查询.
在最好的情况下,您可以授予他们访问视图而不是真实表的权限,并在视图中放置where子句.
简单而丑陋的解决方案
如果我正确理解您的要求:
用户A在您的程序中输入查询.
用户B可以运行它(但不能编辑它)并查看返回的数据.此外,她可以使用您提供的某种窗口小部件根据返回的列添加过滤器.
您不希望在应用程序中应用过滤器,而是将它们添加到查询中,以避免从数据库中获取不必要的数据.
在这种情况下:
当编辑查询尝试运行它并收集返回列的元数据时.如果ColumnName
s不是唯一的,请向作者投诉.使用查询存储元数据.
当B添加过滤器(基于查询元数据)时,存储列名称和条件.
执行时:
检查过滤器列是否仍然有效(A可能已更改查询).如果没有删除无效过滤器和/或通知B.
执行查询如下:
select * from ({query entered by A}) x where x.Column1 op1 Value1 and x.Column2 op2 Value2
如果要优雅地处理数据库架构更改,则需要添加一些额外的检查以确保元数据与查询实际返回的内容一致.
安全说明
您的程序将直接将用户A写入的查询传递给数据库.使用不超过A的数据库权限的权限使用数据库连接来执行此操作至关重要.否则,您要求基于SQL注入的漏洞利用.
推论
如果用户A出于安全原因无法直接访问数据库,则无法使用上述解决方案.
在这种情况下,确保其安全的唯一方法是确保您的应用程序理解100%的查询,这意味着在您的程序中解析它并仅允许您认为安全的操作.