如何从SQL语句中获取列和表

本文关键字:获取 语句 SQL | 更新日期: 2023-09-27 17:50:59

我需要获得查询中使用的列和表,但我没有找到一种优雅的方法来实现它。我已经搜索过了,但找不到对我有用的信息。查询的格式为

select TABLE1.Id, TABLE2.Name, TABLE3.Observations, TABLE3.Adress, --and more 70 fields
from TABLE1, TABLE2, TABLE3, TABLE4

有什么好的方法可以同时完成这两项任务吗?

如何从SQL语句中获取列和表

您的问题是SqlCommand.Parameters是一系列SqlParameter对象,将在查询中替换为实际值。即它们是输入参数。它们用于SqlCommandSQL SafeCompatible表示所包含的参数。例如,对于您的查询,像下面这样的内容就足够了:

SqlCommand sql = new SqlCommand("SELECT TABLE1.Id, TABLE2.Name, TABLE3.Observations, TABLE3.Address FROM TABLE1, TABLE2, TABLE3, TABLE4 WHERE TABLE2.Name = @Name")
sql.Parameters.Add(new SqlParameter("@Name", SqlDbType.NVarChar, 32));
sql.Parameters["@Name"] = "Your Name";

SQL驱动程序然后将查询中的@Name替换为'Your Name'SQL Safe表示。

要做你想做的,你需要解析实际的字符串,并把它分解成标记语句。对于某些语句,这是一个复杂的过程。

根据您的需求(为了支持语法),您可以很容易地通过提取SELECTFROM之间的所有内容来分解语句,在本例中,用逗号分隔字符串,然后用句点进一步分隔以获得表名和字段名。

一些示例代码应该做你想做的(目前尚未测试):

// sql.CommandText can be replaced with the raw SQL Query String
string query = sql.CommandText;
string removeSelect = query.Substring(7); // Remove the SELECT and space
string removeAfterFrom = removeSelect.Substring(0, removeSelect.IndexOf(" FROM ")); // Remove the FROM
string[] columns = removeAfterFrom.Split(','); // Get each Column
List<string> tables = new List<string>();
for (int i = 0; i < columns.Length; i++)
{
    string[] columnName = columns[i].Split('.');
    if (columnName.Length > 1)
        if (!tables.Contains(columnName[0]))
            tables.Add(columnName[0].Trim());
}

还有一点需要注意,这段代码可以很容易地修改为从FROM子句中提取表名。

从本质上讲,这里的目标是创建一个基本的SQL解析器,它可以从SQL语句返回某些值/对象。如果始终是SELECT语句,则此方法将适用于所有变体,除了那些使用通配符(*)列名的变体,或者那些使用TOP (n)的变体。如果必须支持TOP (n)查询,则应该添加适当的筛选器。它还将只返回包含在列名子句中的表名。(即需要完全限定的名称:SELECT TABLE1.Name FROM TABLE1而不是SELECT Name FROM TABLE1

如果您希望获得查询中指定的所有表(无论是否从中选择了任何列),您可以使用以下命令。

// sql.CommandText can be replaced with the raw SQL Query String
string query = sql.CommandText;
string removeSelect = query.Substring(7); // Remove the SELECT and space
string[] splitOnFrom = removeSelect.Split(new string[] { " FROM " }, StringSplitOptions.RemoveEmptyEntries);
string[] columns = splitOnFrom[0].Split(','); // Get each Column
string[] tables = splitOnFrom[1].Split(','); // Get each Table

columns数组包含所有全限定列名,tables数组包含所有全限定表名。

关于这两种方法的另一个侧边栏:FROM 术语(单词)是区分大小写的。即From, from不能工作。如果您希望使用第一种方法并使from不区分大小写,则可以使用以下方法:
string removeAfterFrom = removeSelect.Substring(0, removeSelect.IndexOf(" FROM ", StringComparison.CurrentCultureIgnoreCase));

对于第二个,您需要对它进行更多的修改,但这并不太难。


据我所知,没有任何内置的东西具有这个功能。(不过我敢肯定,谷歌一下就能证明我错了。)

我现在能想到的方法有很多

第一个是实际执行有问题的SQL语句(可能将其包装在begin tran/rollback tran中),然后从SqlDataReader中提取列名。

第二种方法是手工生成一个基本的解析器。这可能非常简单,特别是如果您只需要支持select a.b, c, d.e from ...语法。