18

我正在 SSIS 中创建一个 ETL,我希望我的数据源是一个受限查询,例如select * from table_name where id='Variable'. 这个变量是我定义为用户创建的变量。

我不明白如何让我的源查询与 SSIS 范围变量交互。

目前唯一的选择是

  • 桌子
  • 来自变量的表
  • SQL 命令
  • 来自变量的 SQL 命令

我想要的是有一个以变量为参数的 SQL 语句

4

3 回答 3

32

简单的。选择SQL command作为数据访问模式。使用问号作为参数占位符输入您的查询。然后单击Parameters按钮并将您的变量映射到Parameter0对话框中Set Query Parameters

在此处输入图像描述

更多信息可在MSDN上找到。

于 2013-08-17T19:19:22.030 回答
13

@Edmund 方法的次要替代方法是在另一个变量上使用表达式来构建您的字符串。假设您已经定义了@[User::FirstName],那么您将创建另一个变量@[User::SourceQuery]。

在此变量的属性中,将 EvaluateAsExpression 设置为True,然后设置一个表达式,如"SELECT FirstName, LastName, FROM Person.Person WHERE FirstName = '" + @[User::FirstName] +"'"双引号是必需的,因为我们正在构建一个 SSIS 字符串。

不应该请求这种方法有两个重要原因。

缓存

这种方法会使 SQL Server 中的计划缓存膨胀,其中包含 N 个基本相同查询的副本。第一次运行并且值为“Edmund”时,SQL Server 将创建一个执行计划并保存它(因为构建它们可能很昂贵)。然后运行包,值为“Bill”。SQL Server 检查它是否有这方面的计划。它没有,它只有一个给 Edmund,所以它创建了另一个计划副本,这次硬编码给 Bill。泡沫-冲洗-重复并观察您的可用内存减少,直到它卸载一些计划。

通过使用参数方法,当计划提交给 SQL Server 时,它应该在内部创建计划的参数化版本,并假定提供的所有参数将导致执行成本相等。一般来说,这是期望的行为。

如果您的数据库针对临时工作负载进行了优化(默认情况下关闭该设置),则应该减轻这种情况,因为每个计划都将被参数化。

SQL 注入

您在构建自己的字符串时会遇到的另一个大麻烦是您对 SQL 注入攻击敞开心扉,或者至少,您可能会遇到运行时错误。它就像具有“d'Artagnan”的值一样简单。该单引号将导致您的查询失败,从而导致包失败。将值更改为 "';DROP TABLE Person.Person;--" 将导致极大的痛苦。

您可能认为安全引用所有内容是微不足道的,但在您查询的任何地方始终如一地实施它的努力超出了您的雇主支付给您的费用。更是如此,因为提供了本机功能来做同样的事情。

于 2013-08-18T15:12:11.890 回答
2

使用 OLEDB 连接管理器(在我的情况下使用 SQL Server Native Client 11.0 提供程序)时,您可能会遇到如下错误:

无法从 SQL 命令中提取参数。提供程序可能无法帮助解析命令中的参数信息。在这种情况下,请使用“来自变量的 SQL 命令”访问模式,其中整个 SQL 命令都存储在一个变量中。

因此,您需要在 OLEDB 连接管理器属性中明确指定数据库名称。否则,SQL Server Native Client 可以使用与您的意思不同的数据库名称(例如 MSSQL Server 中的 master)。在某些情况下,您可以为查询中使用的每个数据库对象显式指定数据库名称,例如:

select Name
from MyDatabase.MySchema.MyTable
where id = ?
于 2019-04-03T14:12:48.883 回答