【问题标题】:SQL Server how to link a column name to an external variable?SQL Server 如何将列名链接到外部变量?
【发布时间】:2021-04-07 11:48:14
【问题描述】:

我在SQL中做了一个代码,将一个项目与一列的每条记录分开而不重复,并且它工作正常,请按照以下代码:

SELECT DISTINCT Tab_Dados_Escolha.Nome_Produto FROM Tab_Dados_Escolha

但是我想用一个外部变量替换这个例程将在其中完成的列的名称,所以我可以对其他列使用相同的代码,而不必重写另一个代码,我无法做到这一点到目前为止,有人可以帮助我吗?

【问题讨论】:

  • 您必须使用动态 SQL —— 即将查询构造为字符串,然后执行它。不建议这样做,因为它会使代码容易受到 SQL 注入攻击和意外的语法错误。
  • 您不能使用变量来替换文字,您必须使用动态 SQL 并且 安全地 将值注入语句中。此外,对于这样的事情,您最好使用DISTINCT 而不是GROUP BYGROUP BY 意味着在执行某种形式的聚合时使用。
  • 你不能。表和列等价于强类型函数语言中的类型和字段。当查询引擎解析查询时,必须知道它们的模式。 SQL 查询是编译成执行计划的语言,就像 C# 或 F# 代码编译成可执行文件一样。查询参数与程序的参数相同。它们不会影响已编译的程序,它们是它使用的数据
  • 我怀疑这真的是XY Problem。您在这里真正要解决的问题是什么?
  • 确实,该查询本质上是一个DISTINCT。那为什么要使用GROUP BY呢?你想避免什么重复?您是否尝试像 Pandas 或 .NET DataFrame 那样分析表格的内容?这些库不会单独计算度量,因为这需要多次读取数据。为每一列执行 DISTINCT 意味着您多次扫描整个表。这些库在逐行扫描数据的同时计算多个度量

标签: sql sql-server database


【解决方案1】:

我正在回答这里提出的问题,但是,正如我所提到的,它具有XY Problem 的外观和“气味”。因此,您真的应该询问您真正想要解决的问题,并且应该(现在)在一个新问题中。

至于您所问的,正如 cmets 告诉您的那样,您不能使用变量/参数来替换列文字。采取如下方式:

DECLARE @ColName sysname;
SET @ColName = N'Nome_Produto';

SELECT DISTINCT @ColName
FROM dbo.Tab_Dados_Escolha;

不会Nome_Produto 列中的每个不同值返回一行。相反,它将返回值为N'Nome_Produto' 的单行和列。就是这样。这是因为变量/参数没有被解释为“返回具有@ColName 值的列的值”,而只是“返回@ColName 的值”。

因此,您需要使用动态 SQL 并安全地注入值。我还建议验证传递的值,这样如果该列不存在,您就不会运行任何(动态)SQL。这意味着您需要执行以下操作:

DECLARE @Colname sysname; --Your Parameter
SET @ColName = N'Nome_Produto'; --Parameter Value

DECLARE @SQL nvarchar(MAX);

SELECT @SQL = N'SELECT DISTINCT ' + QUOTENAME(c.[name]) + N' FROM dbo.Tab_Dados_Escolha;'
FROM sys.schemas s
     JOIN sys.tables t ON s.schema_id = t.schema_id
     JOIN sys.columns c ON t.object_id = c.object_id
WHERE s.[name] = N'dbo' --assumed
  AND t.[name] = N'Tab_Dados_Escolha'
  AND c.[name] = @Colname;

EXEC sys.sp_executesql @SQL;

当然,这些都没有涉及动态 SQL 的参数化等,但这也是一个非常不同的问题。

但是,除非您真的知道自己在用它做什么,否则真的不推荐使用动态 SQL。如果你连这么简单的东西都不懂,就不要使用它。相反,请重新考虑您的设计,因为它可能存在缺陷。

【讨论】:

  • 感谢您的帮助,我有一个大型数据库,我正在尝试开发一个查询该数据库的应用程序,请求的查询是显示确定列中所有名称的列表在数据库中,不再重复,我选择了这条路,谢谢
  • 为什么这需要动态查询,@VitorMarquesLourenço ...它不需要。
  • 我希望将此代码扩展到数据库中该表的所有列以及其他表,这样我只使用一个代码并可以查询其他表,将外部变量@ColName替换为鼠标选中的列名,谢谢大家的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-11
  • 1970-01-01
  • 2012-08-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多