sql - 根据另一个数据库的查询结果查询一个数据库

标签 sql sql-server ssis etl ssis-2012

我在 VS 2013 中使用 SSIS。 我需要从 1 个数据库获取 ID 列表,并使用该 ID 列表查询另一个数据库,即 SELECT ... from MySecondDB WHERE ID IN ({list of IDs from MyFirstDB}).

最佳答案

有 3 种方法可以实现此目的:

第一种方法 - 使用查找转换

首先,您必须添加一个 Lookup Transformation 就像 @TheEsisia 回答的那样,但还有更多要求:

  • 在查找中,您必须编写包含 ID 列表的查询(例如:SELECT ID From MyFirstDB WHERE ...)

  • 至少您必须从查找表中选择一列

  • 这些不会过滤行,但会添加第二个表中的值

要过滤行WHERE ID IN ({list of IDs from MyFirstDB}),您必须在查找错误输出中做一些工作错误情况有两种方法:

enter image description here

  1. 将错误处理设置为忽略行,以便添加的列(来自查找)值为 null ,因此您必须添加一个条件拆分来过滤具有相等值的行无效的。

假设您选择了 col1 作为查找列,因此您必须使用类似的表达式

ISNULL([col1]) == False
  • 或者您可以将错误处理设置为Redirect Row,这样所有行都会被发送到错误输出行,该行可能不会被使用,因此数据将被过滤
  • 这种方法的缺点是所有数据在执行过程中都会被加载和过滤。

    此外,如果在加载所有数据后在本地计算机上完成网络过滤(服务器上的第二种方法),则内存会被加载。

    第二种方法 - 使用脚本任务

    为了避免加载所有数据,您可以采取一种解决方法,您可以使用脚本任务来实现此目的:(用 VB.NET 编写的答案)

    假设连接管理器名称为 TestAdo"Select [ID] FROM dbo.MyTable" 是获取 id 列表的查询,并且User::MyVariableList 是您要存储 id 列表的变量

    注意:此代码将从连接管理器读取连接

        Public Sub Main()
    
            Dim lst As New Collections.Generic.List(Of String)
    
    
            Dim myADONETConnection As SqlClient.SqlConnection  
        myADONETConnection = _  
            DirectCast(Dts.Connections("TestAdo").AcquireConnection(Dts.Transaction), _  
            SqlClient.SqlConnection)
    
            If myADONETConnection.State = ConnectionState.Closed Then
            myADONETConnection.Open()
            End If
    
            Dim myADONETCommand As New SqlClient.SqlCommand("Select [ID] FROM dbo.MyTable", myADONETConnection)
    
            Dim dr As SqlClient.SqlDataReader
    
            dr = myADONETCommand.ExecuteReader
    
            While dr.Read
    
                lst.Add(dr(0).ToString)
    
            End While
    
    
            Dts.Variables.Item("User::MyVariableList").Value = "SELECT ... FROM ... WHERE ID IN(" &  String.Join(",", lst) & ")"
    
            Dts.TaskResult = ScriptResults.Success
        End Sub
    

    并且 User::MyVariableList 应该用作源(变量中的 Sql 命令)

    第三种方法 - 使用执行 Sql 任务

    与第二种方法类似,但这将使用执行 SQL 任务构建 IN 子句,然后使用整个查询作为OLEDB Source

    1. 只需在 DataFlow 任务之前添加一个执行 SQL 任务
    2. ResultSet 属性设置为 single
    3. 选择User::MyVariableList 作为结果集
    4. 使用以下 SQL 命令

      DECLARE @str AS VARCHAR(4000)
      
      SET @str = ''
      
      SELECT @str = @str + CAST([ID] AS VARCHAR(255)) + ','
      FROM dbo.MyTable 
      
      SET @str = 'SELECT * FROM  MySecondDB WHERE ID IN (' + SUBSTRING(@str,1,LEN(@str) - 1) + ')'
      
      SELECT @str
      

    enter image description here

    enter image description here

    如果列具有字符串数据类型,您应该在值之前和之后添加引号,如下所示:

    SELECT @str = @str + '''' + CAST([ID] AS VARCHAR(255)) + ''','
        FROM dbo.MyTable
    

    确保您已将 DataFlow Task Delay Validation 属性设置为 True

    关于sql - 根据另一个数据库的查询结果查询一个数据库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43746258/

    相关文章:

    sql-server - 在 SSIS 中生成唯一标识符 GUID

    mysql - select 语句将一个表中的列相乘,然后添加另一表中的列

    sql - 当列的数据类型为 int 时如何用字符串替换 null

    mysql - 复杂的SQL查询: Select like tree traversal

    sql - 仅插入具有相同 id 的最高值

    mysql - 对大量行运行 SUM

    postgresql - SQL 查询错误 : The query failed to parse. HResult 异常:0x80040E14

    sql - PostgreSQL:以主键作为排序键的 ORDER BY 非常慢

    mysql - 如何将来自不同供应商的不同数据库的不同列的数据合并到一张表中?

    c# - SSIS:无法将类型为 'System.Decimal' 的对象转换为类型 'System.Char[]'