当前位置: 首页 > 面试题库 >

从查询中获取表架构

潘皓
2023-03-14
问题内容

根据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保留别名,那么实际上不可能优化复杂的查询。

可能的解决方案

我建议重申一个问题:

  1. 您(或您的应用程序)是否在查询中?在这种情况下,您应该知道别名。

  2. 如果您收到其他人提供的查询…那么…这取决于您为什么要在何处添加原因。

    • 在最坏的情况下,您必须自己解析查询。

    • 在最佳情况下,您可以授予他们访问视图的权限,而不是实际表的访问权限,然后在视图中放置where子句。

简单丑陋的解决方案

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

  • 用户A在您的程序中输入查询。

  • 用户B可以运行它(但不能编辑它)并查看返回的数据。另外,她可以使用您提供的某种小部件根据返回的列添加过滤器。

  • 您不想在应用程序内部应用过滤器,而是将其添加到查询中,以避免从数据库中获取不必要的数据。

在这种情况下:

  • 当A编辑查询尝试运行它并收集返回列的元数据。如果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%的查询,这意味着在您的程序中对其进行解析,并仅允许您认为安全的操作。



 类似资料:
  • 问题内容: 在我的代码中,我正在使用。 然后,我执行该方法以填充准备好的语句的通配符。 在调用该方法并执行查询之前,我是否有办法检索(并打印出)最终查询?我只想将此用于调试目的。 问题答案: 这在JDBC API合同中没有定义,但是如果幸运的话,有问题的JDBC驱动程序可以通过调用来返回完整的SQL 。即 以我的经验,至少这样做是PostgreSQL 8.x和MySQL 5.x JDBC驱动程序。

  • 问题内容: 我正在尝试连接到数据库,运行查询并打印出查询。到目前为止,我已经完成了工作,但是我需要获取输出并将其中的特定部分分配给 我正在使用log4jdbc监视我的查询。 此刻,我得到如下记录的输出: 我想分配给。我该怎么做呢? 问题答案: 通常,a 将为您提供查询(包括绑定参数)。但这取决于的实际实现(例如,使用PostgreSQL隐式实现)。 您提到为您带来回报。我对 log4jdbc 并不

  • 我试图从获取数据。总共有9个表格,我必须相应地从所有表格中显示产品列表。 我考虑过使用连接,并尝试了左连接,如下所示: 这里是主表,pid是从tbl2到tbl9的所有表的。 注意:这里我在所有表上使用了来避免长查询,但是在实际的数据库操作中,只提到特定的列来提高性能。 现在实际的问题是,我没有得到所有的记录从表使用左加入。只检索中对应的每个条目的最后一行。 我使用了GROUP BY来避免重复的左连

  • 问题内容: 我正在尝试一次从三个表中检索数据。这些表如下所示: 类别 讯息 评论 我想要得到的是1条消息(因为我有一个基于id的子句),3个类别(因为有3个类别链接到消息)和2条注释(因为有2条注释链接到消息)。 我正在尝试使用以下查询来检索数据: 但是,当运行此查询时,我得到6个结果: 在我预期结果如下的地方: 只有三行,我应该能够获取所有需要的数据。这有可能吗?我做错了吗?? 问题答案: 如评

  • 问题内容: 我在Oracle数据库11g中使用Pl / SQL。 我正在编写一个将select语句作为参数(varchar2)的函数。该函数使用for循环遍历行并将格式应用于特定的列,并输出整个内容。基本上,我需要某种方式来获取列名,以便可以在顶部显示它们。我知道有多种方法可以对表执行此操作,但是由于传入了此查询,因此可能未选择所有列,可能已使用别名等。 有没有一种方法可以从此查询中选择列名? 理

  • 问题内容: 我仍然很陌生,尽管在SO上看到与此类似的多个问题,但我无法重现某些OP所要求的输出。 我正在做一些相当简单的事情,我在mongo中找到了一个集合,而我要做的就是将值作为字符串返回。我将最终将这些问题推向NSQ,但这是我的首要任务。 今天输出: 我浏览了bson#m文档,并认为我正确使用了地图以增加价值。所以我认为,我的查询结果是: 但是如果ObjectIdHex(“ ID”)是值,我该