SQL/C# - 将函数应用于 SQL 查询中的列

SQL/C# - Apply a function to columns within a SQL query

有没有办法解析给定的 SQL SELECT 查询并用函数调用包装每一列,例如dbo.Foo(column_name) 在 运行 之前 SQL 查询?

我们已经研究过在列名上使用正则表达式类型 'replace',但是,我们似乎无法解释可以编写 SQL 查询的所有方式。

SQL 查询的一个例子是;

SELECT 
    [ColumnA]
  , [ColumnB]
  , [ColumnC] AS [Column C]
  , CAST([ColumnD] AS VARCHAR(11)) AS [Bar]
  , DATEPART([yyyy], GETDATE()) - DATEPART([yyyy], [ColumnD]) AS [Diff]
  , [ColumnE]
FROM [MyTable]
WHERE LEN([ColumnE]) > 0
ORDER BY 
    [ColumnA]
  , DATEPART([yyyy], [ColumnD]) - DATEPART([yyyy], GETDATE());

我们需要的结果是;

SELECT 
    [dbo].[Foo]([ColumnA])
  , [dbo].[Foo]([ColumnB])
  , [dbo].[Foo]([ColumnC]) AS [Column C]
  , CAST([dbo].[Foo]([ColumnD]) AS VARCHAR(11)) AS [Bar]
  , DATEPART([yyyy], GETDATE()) - DATEPART([yyyy], [dbo].[Foo]([ColumnD])) AS [Diff]
  , [dbo].[Foo]([ColumnE])
FROM [MyTable]
WHERE LEN([dbo].[Foo]([ColumnE])) > 0
ORDER BY 
    [dbo].[Foo]([ColumnA])
  , DATEPART([yyyy], [dbo].[Foo]([ColumnD])) - DATEPART([yyyy], GETDATE());

上述任何或所有列可能需要对其调用的函数(包括 WHEREORDER BY 中使用的列),这就是我们需要查询范围解决方案的原因。

我们有很多像上面这样的预写查询需要更新,这就是为什么手动更新会很困难。

上面的例子表明,一些结果列可能被计算出来,而一些只是被重命名了。大多数也由连接组成,有些包含我为了这个例子的目的而省略的 case 语句。

另一种需要考虑的情况是 table 名称别名,例如SELECT t1.ColumnA, t2.ColumnF

解决此问题的 SQL 或 C# 解决方案是理想的选择。

您可以替换语句...

,而不是替换每一列的每次出现
FROM MyTable

...使用包含所有现有列的子选择以及函数调用:

FROM (
    SELECT dbo.Foo(ColumnA) AS ColumnA, dbo.Foo(ColumnB) AS ColumnB,
        dbo.Foo(ColumnC) AS ColumnC --etc.
    FROM MyTable
) AS MyTable

查询的其余部分可以保持不变。在 table 别名的情况下,您只需将 AS Table1 替换为 AS t1

您应该考虑的另一个选择是在您的数据库中创建本质上是子选择的视图。结合命名约定,您可以轻松地将 FROM(和 JOIN)语句中出现的内容替换为视图名称:

FROM MyTable_Foo AS t1

如果您想替换您将要使用的 所有 查询,请考虑重命名 table 并创建与旧 [=33] 一样命名的视图=]s.


更笼统的说明:您应该重新考虑您对根本问题的处理方法,因为您在这里所做的会带走 SQL 的大部分功能。最糟糕的是,一旦你在所有列上调用该函数,你将无法在这些列上使用索引,这可能意味着对数据库性能的严重影响。