.net – 从查询中获取表模式

前端之家收集整理的这篇文章主要介绍了.net – 从查询中获取表模式前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
根据 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时,它提供联系而不是别名c.有没有办法从上面的查询获取表模式和别名?

任何帮助都会很棒!

编辑

虽然我可以使用Rob建议的执行计划,但我会欣赏任何其他简单的方法.

通过tomekszpakowicz回答问题

Are you (or your application) source
of the query in question? In that case
you should know the aliases.

我不是查询的作者.我们有一个用户可以输入查询的系统.我们使用上面解释的方法从中构建列.这些细节将被保留,另一个用户可以使用它来添加新标准等.因此我们需要根据我们的信息动态构建sql.因此,当列具有别名并且我们没有获得别名时,则构造的where子句将无效.

谢谢

解决方法

简短的回答

这不行.根据设计,您无法从结果模式中获取表别名.而且你不能依赖于能够从查询执行计划中获取它们.

答案很长

当您获得SQL查询的结果时,该查询已经被解析,验证,优化,编译成一些内部表示并执行.别名是查询的“源代码”的一部分,通常在步骤1和2的某处丢失.

在执行查询之后,唯一可以看作表的东西是a)真实的物理表和b)返回的数据看作单个匿名表.两者之间的所有内容都可以进行转换或完全优化.

如果要求DBMS保留别名,则实际上不可能优化复杂查询.

可能的解决方

我建议重述一个问题:

>您(或您的应用程序)是否有问题的查询来源?在这种情况下,您应该知道别名.
>如果你得到别人提供的查询……那么……这取决于你为什么要添加原因.

>在最坏的情况下,您必须自己解析查询.
>在最好的情况下,您可以授予他们访问视图而不是真实表的权限,并在视图中放置where子句.

简单而丑陋的解决方

如果我正确理解您的要求:

>用户A在您的程序中输入查询.
>用户B可以运行它(但不能编辑它)并查看返回的数据.
此外,她可以使用您提供的某种窗口小部件根据返回的列添加过滤器.
>您不希望在应用程序中应用过滤器,而是将它们添加查询中,以避免从数据库获取不必要的数据.

在这种情况下:

>当编辑查询时,尝试运行它并收集返回列的元数据.
如果ColumnNames不是唯一的,请向作者投诉.
使用查询存储元数据.
>当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%的查询,这意味着在程序中解析它并仅允许您认为安全的操作.

猜你在找的MsSQL相关文章