2017-07-14 210 views
0

我正在創建一個新的SSIS 2008 ETL報表,它將從SQL Server讀取數據並將其附加到ACCESS 2010數據庫表中。當Access表中存在標識列時,如何將記錄附加到現有的訪問表中?SSIS 2008:將SQL數據導出到Access數據庫2010表

我目前的解決方案有一個SQL讀取數據的OLE DB源。它連接到數據轉換任務,然後連接到OLE DB目標任務。訪問表中的標識字段被命名爲「Id」,並且它是一個自動編號字段。

當Access表爲空時,我可以使用OLE DB目標插入值。問題與身份字段以及表中已有記錄的時間有關。

所以,問題是,我的Id列總是從1開始,這意味着我得到一個錯誤,因爲引擎認爲我想插入一個重複密鑰。

我創建了一個SQL Task,它從表中讀取最大ID並將其存儲到一個變量中,但現在我試圖弄清楚如何在數據流導出過程中使用此值。

有人請告訴我如何在表中已有記錄時將數據插入到Access數據庫中?

編輯的清晰度。我添加了下面用來獲取所需SQL記錄的SQL。請注意,我不包括我的SQL中的ID標識字段:

DECLARE @STARTDATE DATETIME = (SELECT CONVERT(VARCHAR(25),DATEADD(DD,-(DAY(DATEADD(MM,4,GETDATE()))-1), 
DATEADD(MM,4,GETDATE())),101)) 

DECLARE @ENDDATE DATETIME = (SELECT CONVERT(VARCHAR(25),DATEADD(DD,-(DAY(DATEADD(MM,5,GETDATE()))), 
DATEADD(MM,5,GETDATE())),101)) 

SELECT DISTINCT 
         ISNULL(CONVERT(VARCHAR(3),PP.LOBCD),'CPP') 'LOB_Name_Product' 
        , POLICYID 'Policy_#' 
        , P.PRODUCERID 'Agent_#' 
        , CONVERT(VARCHAR(14),POLICYEFFDT,101) 'Policy_Eff_Date' 
        , CONVERT(VARCHAR(14),TS.POLICYEXPDT,101) 'Policy_Exp_Date' 
        , CONVERT(NUMERIC(15,2),TS.TERMPREMAMT) 'Inforce_Prem_Sum' 
        , REPLACE(CONVERT(CHAR(100),REPLACE(REPLACE(N.INSUREDNM,CHAR(10),' '),CHAR(13),'')),',',' ') AS 'Insured_Name' 
        , REPLACE(P.PRODUCERNM1TX,',',' ') AS 'Agent_Name' 
        , PD.PREDSTATECD 'Policy_State' 
        , REPLACE(II.ADDRLINE1TX ,',',' ') AS 'Insured_Address_1' 
        , REPLACE(ISNULL(II.ADDRLINE2TX,''),',',' ') AS 'Insured_Address_2' 
        , II.CITYNM 'Insured_City' 
        , II.STATECD 'Insured_State' 
        , CASE WHEN LEN(RTRIM(II.ZIPCD)) > 5 THEN (SUBSTRING(II.ZIPCD,1,5) + '-' + SUBSTRING(II.ZIPCD,6,5)) 
         ELSE II.ZIPCD 
         END 'Insured_Zip' 
        , REPLACE(P.PRODUCERADDRLINE1TX,',',' ') AS 'Agent_Address_1' 
        , REPLACE(ISNULL(P.PRODUCERADDRLINE2TX,''),',',' ') AS 'Agent_Address_2' 
        , P.PRODUCERCITYNM 'Agent_City' 
        , P.STATECD 'Agent_State' 
        , CASE WHEN LEN(RTRIM(P.ZIPCD)) > 5 THEN SUBSTRING(RTRIM(P.ZIPCD),1,5) + '-' + SUBSTRING(RTRIM(P.ZIPCD),6,5) 
         ELSE P.ZIPCD 
         END 'Agent_Zip' 
        , CONVERT(VARCHAR(10), GETDATE(), 101) AS 'Upload_Date' 
        , 'Open' AS 'Status'      

FROM COPOLICYPOINTER PP 

JOIN COTRANSACTIONSUMMARY TS ON TS.SYSTEMASSIGNID = PP.SYSTEMASSIGNID 
AND TS.TRANSSEQNO = ( SELECT MAX(TRANSSEQNO) FROM COTRANSACTIONSUMMARY TS2 
                WHERE TS2.SYSTEMASSIGNID = TS.SYSTEMASSIGNID) 
AND TS.TRANSEFFDT = (  SELECT MAX(TRANSEFFDT) FROM COTRANSACTIONSUMMARY TS2 
                WHERE TS2.SYSTEMASSIGNID = TS.SYSTEMASSIGNID) 

JOIN COPOLICYDETAIL PD ON TS.SYSTEMASSIGNID = PD.SYSTEMASSIGNID 
AND PD.TRANSSEQNO = ( SELECT MAX(TRANSSEQNO) FROM COPRODUCER PD2 
                WHERE PD2.SYSTEMASSIGNID = PD.SYSTEMASSIGNID) 

JOIN COPRODUCER P ON P.SYSTEMASSIGNID = TS.SYSTEMASSIGNID 
AND P.TRANSSEQNO = ( SELECT MAX(TRANSSEQNO) FROM COPRODUCER P2 
               WHERE P2.SYSTEMASSIGNID = P.SYSTEMASSIGNID) 

JOIN COINSUREDNAME N ON N.SYSTEMASSIGNID = P.SYSTEMASSIGNID 
AND N.TRANSSEQNO = ( SELECT MAX(TRANSSEQNO) FROM COINSUREDNAME N2 
               WHERE N2.SYSTEMASSIGNID = N.SYSTEMASSIGNID) 

JOIN COINSUREDINFO II ON II.SYSTEMASSIGNID = N.SYSTEMASSIGNID 
AND II.TRANSSEQNO = ( SELECT MAX(TRANSSEQNO) FROM COINSUREDINFO I2 
               WHERE I2.SYSTEMASSIGNID = II.SYSTEMASSIGNID) 

WHERE TS.POLICYEXPDT BETWEEN @STARTDATE AND @ENDDATE 
AND PP.CANCEFFDT IS NULL 
AND PD.PREDSTATECD IN ('CT', 'RI', 'GA','NH','NY') 

ORDER BY POLICYID 

結果與數據轉換任務相關聯。

數據轉換任務然後鏈接到OLE DB目標任務。

OLE DB目標任務使用連接到Access數據庫的OLE DB提供程序。這個數據庫中的一個表稱爲MasterTable,它有一個名爲ID的自動編號字段。

我添加了下面整個工作流程的屏幕截圖。

  1. 高級別數據流

enter image description here

  • OLE DB目標連接信息來訪問數據庫 enter image description here
  • +0

    我的理解是,關閉自動編號是不可能的。自動編號是Access中的一個字段類型,不像SQL Server中的整數列那樣。 –

    +0

    是的,先生,謝謝你的答覆。但是必須有某種獲取記錄的方式,將當前標識值添加到我的SQL中,然後將記錄附加到訪問表中?這不可能是第一次出現這個問題。 :) – WorkJ

    +0

    即使有所有的解釋,目前還不清楚你想用自動編號字段做什麼。 1)您不需要在INSERT(即附加)查詢中指定自動編號字段。它將自動填入下一個有效的號碼。 2)但是,如果您試圖在該自動編號字段中輸入特定值,那麼爲什麼首先將其作爲自動編號字段?如果值通過「轉換任務」形成SQL Server,則將這些值插入標準數字字段(例如,非自動編號,長)。 –

    回答

    0

    我發現了一個方法來做我需要的東西,所以我在這裏發佈答案,以防其他人幫助。我將總結下面的步驟,然後發佈代碼。我使用SSIS 2008

    我來源於相關的答案,我在此網站上發現這樣的回答: ​​3210

    1. 創建一個數據流任務

    2. 在數據流任務,創建一個帶有SQL代碼的OLE Db源代碼。這是可以將結果放入您的訪問表的查詢。

    3. 一旦我得到了SQL的工作,我創建了一個數據轉換任務,並將大多數列轉換爲unicode(日期列除外)。請注意轉換器「輸出別名」列中的名稱。這些是您在下面顯示的C#腳本任務中使用的名稱。

    4. 將結果保存到記錄集目的地。當您創建記錄集時,「組件屬性」選項卡具有名爲VariableName的字段。在那裏放一個變量。該變量將保存SQL查詢的結果。我將它命名爲「rsSourceTable」。這個變量是C#代碼讀取的結果集。

    5. 一旦你得到數據流任務工作,創建一個C#腳本任務。我創建了幾個變量供腳本任務使用。


      只讀變量:
      AccessPath - 保存Access文件所在的路徑。
      rsSourceTable - 保存我們數據流任務結果的變量。

      讀/寫變量: MasterTableRowCount - 我使用它可以很容易地報告插入日誌文件和電子郵件任務中的文件數量。


    6.腳本任務的c#代碼如下所示。我不必添加任何對此的引用。

    using System; 
    using System.Data; 
    using Microsoft.SqlServer.Dts.Runtime; 
    using System.Windows.Forms; 
    using System.Data.OleDb; 
    
    namespace ST_afd8e3cca5534e51ba5855e82f502e92.csproj 
    { 
        [System.AddIn.AddIn("ScriptMain", Version = "1.0", Publisher = "", Description = "")] 
        public partial class ScriptMain : Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase 
        { 
    
         #region VSTA generated code 
         enum ScriptResults 
         { 
          Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success, 
          Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure 
         }; 
         #endregion 
    
         public void Main() 
         { 
          OleDbConnection myConnection = new OleDbConnection(); 
          try 
          { 
           string accessPath = Dts.Variables["AccessPath"].Value.ToString(); 
           string materTableId = Dts.Variables["MasterTableId"].Value.ToString(); 
           myConnection.ConnectionString = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + accessPath; 
           DataTable dt = new DataTable(); 
           OleDbDataAdapter adapter = new OleDbDataAdapter(); 
           adapter.Fill(dt, Dts.Variables["User::rsSourceTable"].Value); 
           int rowCount = 0; 
           if (dt.Rows.Count > 0) 
           { 
            rowCount = dt.Rows.Count; 
            Dts.Variables["MasterTableRowCount"].Value.ToString(); 
            myConnection.Open(); 
            //1. When building the INSERT statement, remember to enclose column names in square brackets. This prevents errors because Access allows special characters in column names and OLE DB doesn't 
            //2. Also remember that the order the column names appear in the INSERT statement is important for the code that adds parameters below. 
            //3. To prevent an error, the INSERT statement is first constructed with a ? for each parameter. The parameter is replaced with the 
            // appropriate column name in the for loop below. 
            string insertString = "INSERT INTO MasterTable ([LOB_Name_Product], [Policy_#], [Policy_State], [Policy_Eff_Date], [Policy_Exp_Date], [Insured_Name], [Insured_Address_1], "; 
            insertString += "[Insured_Address_2], [Insured_City], [Agent_#], [Agent_Name], [Inforce_Prem_Sum], [Status], [Upload_date], [Insured_Zip], [Insured_State], [Agent_Address_1], [Agent_Address_2], [Agent_City], [Agent_Zip], [Agent_State])"; 
            insertString += " Values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; 
            OleDbCommand cmmd = new OleDbCommand(insertString, myConnection); 
            if (myConnection.State == ConnectionState.Open) 
            { 
             cmmd.Parameters.Add("?", OleDbType.VarWChar, 255); //LOB_Name_Product 
             cmmd.Parameters.Add("?", OleDbType.VarWChar, 255); //Policy_# 
             cmmd.Parameters.Add("?", OleDbType.VarWChar, 255); //Policy_State 
             cmmd.Parameters.Add("?", OleDbType.DBDate, 10);  //Policy_Eff_Date 
             cmmd.Parameters.Add("?", OleDbType.DBDate, 10);  //Policy_Exp_Date 
             cmmd.Parameters.Add("?", OleDbType.VarWChar, 255); //Insured_Name 
             cmmd.Parameters.Add("?", OleDbType.VarWChar, 255); //Insured_Address_1 
             cmmd.Parameters.Add("?", OleDbType.VarWChar, 255); //Insured_Address_2 
             cmmd.Parameters.Add("?", OleDbType.VarWChar, 255); //Insured_City 
             cmmd.Parameters.Add("?", OleDbType.VarWChar, 255); //Agent_# 
             cmmd.Parameters.Add("?", OleDbType.VarWChar, 255); //Agent_Name 
             cmmd.Parameters.Add("?", OleDbType.Currency, 255); //Inforce_Prem_Sum 
             cmmd.Parameters.Add("?", OleDbType.VarWChar, 255); //Status 
             cmmd.Parameters.Add("?", OleDbType.Date, 10);  //Upload_date 
             cmmd.Parameters.Add("?", OleDbType.VarWChar, 255); //Insured_Zip 
             cmmd.Parameters.Add("?", OleDbType.VarWChar, 255); //Insured_State 
             cmmd.Parameters.Add("?", OleDbType.VarWChar, 255); //Agent_Address_1 
             cmmd.Parameters.Add("?", OleDbType.VarWChar, 255); //Agent_Address_2 
             cmmd.Parameters.Add("?", OleDbType.VarWChar, 255); //Agent_City 
             cmmd.Parameters.Add("?", OleDbType.VarWChar, 255); //Agent_Zip 
             cmmd.Parameters.Add("?", OleDbType.VarWChar, 255); //Agent_State 
             cmmd.Prepare(); 
             OleDbTransaction trans = myConnection.BeginTransaction(); 
             cmmd.Transaction = trans; 
             foreach(DataRow dr in dt.Rows) 
             { 
              cmmd.Parameters[0].Value = dr["Copy of LOB_Name_Product"]; 
              cmmd.Parameters[1].Value = dr["Copy of Policy_#"]; 
              cmmd.Parameters[2].Value = dr["Copy of Policy_State"]; 
              cmmd.Parameters[3].Value = dr["Policy_Eff_Date"]; 
              cmmd.Parameters[4].Value = dr["Policy_Exp_Date"]; 
              cmmd.Parameters[5].Value = dr["Copy of Insured_Name"]; 
              cmmd.Parameters[6].Value = dr["Copy of Insured_Address_1"]; 
              cmmd.Parameters[7].Value = dr["Copy of Insured_Address_2"]; 
              cmmd.Parameters[8].Value = dr["Copy of Insured_City"]; 
              cmmd.Parameters[9].Value = dr["Copy of Agent_#"]; 
              cmmd.Parameters[10].Value = dr["Copy of Agent_Name"]; 
              cmmd.Parameters[11].Value = dr["Copy of Inforce_Prem_Sum"]; 
              cmmd.Parameters[12].Value = "Open"; 
              cmmd.Parameters[13].Value = DateTime.Today.ToString("d"); 
              cmmd.Parameters[14].Value = dr["Copy of Insured_Zip"]; 
              cmmd.Parameters[15].Value = dr["Copy of Insured_State"]; 
              cmmd.Parameters[16].Value = dr["Copy of Agent_Address_1"]; 
              cmmd.Parameters[17].Value = dr["Copy of Agent_Address_2"]; 
              cmmd.Parameters[18].Value = dr["Copy of Agent_City"]; 
              cmmd.Parameters[19].Value = dr["Copy of Agent_Zip"]; 
              cmmd.Parameters[20].Value = dr["Copy of Agent_State"]; 
              cmmd.ExecuteNonQuery(); 
             } 
             trans.Commit(); 
             myConnection.Close(); 
             Dts.TaskResult = (int)ScriptResults.Success; //add logging here for successful operation 
            } 
            else 
             Dts.TaskResult = (int)ScriptResults.Failure; 
           } 
           else 
            Dts.TaskResult = (int)ScriptResults.Success; //add logging here for no records 
    
          } 
          catch (OleDbException oleEx) 
          { 
           myConnection.Close(); 
           Dts.TaskResult = (int)ScriptResults.Failure; //add logging here for unable to connect 
          } 
          catch (Exception ex) 
          { 
           myConnection.Close(); 
           Dts.TaskResult = (int)ScriptResults.Failure; //add logging here for any other error 
          } 
    
         } 
        } 
    } 
    
    相關問題