2009-07-09 16 views
2

Je souhaite mettre à jour TableA avec les valeurs de TableB tous les soirs. En ce moment, j'essaye de faire ceci avec SSIS 2005 using une tâche de manuscrit avec le SQL dedans. Chaque fois que j'essaie de faire la mise à jour de cette manière, j'obtiens une erreur de temporisation.SSIS Mettre à jour les valeurs de table à partir d'une autre table

Existe-t-il une meilleure façon de faire cela dans SSIS?

Les informations actuelles ci-dessous:

Public Sub Main() 

    Const Component_Name As String = "Updating TableA Data" 
    Const Conn_String As String = "Data Source=DB_A;Initial Catalog=TableA;Integrated Security=SSPI;" 

    Const sql_Emp As String = "Update TableA Set Contract = c.License_No, SEIN = convert(varchar, c.Lic_Exp_Date, 101) " _ 
     & "From Server.DB_B.dbo.TableB c Inner Join TableA b on " _ 
     & "rtrim(ltrim(c.business_lic)) = rtrim(ltrim(cast(b.Account_Key as varchar(14)))) " _ 
     & "Where c.Lic_Exp_Date = (select Max(Lic_Exp_Date) From Server.DB_B.dbo.TableB " _ 
     & "Where rtrim(ltrim(business_lic)) = rtrim(ltrim(cast(b.Account_Key as varchar(14))))) " _ 
     & "and convert(varchar, c.Lic_Exp_Date, 101) <> convert(varchar, b.SEIN, 101)" 

    Dim con As SqlConnection = New SqlConnection(Conn_String) 

    Try 
     Dts.Log("Opening DB Connection: " & con.ConnectionString, 0, Nothing) 

     con.Open() 

     Dim duh As New SqlCommand(sql_Emp, con) 
     duh.ExecuteNonQuery() 

     con.Close() 

     Dts.Log(String.Format(Component_Name), 0, Nothing) 
     Dts.Events.FireInformation(0, Component_Name, String.Format("TableA Data Updating"), "", 0, True) 

     Dts.TaskResult = Dts.Results.Success 

    Catch ex As Exception 
     Dts.Events.FireError(0, Component_Name, ex.Message, "", 0) 
     Dts.Log("Exception detected: " & ex.ToString, 0, Nothing) 
     Dts.TaskResult = Results.Failure 

    End Try 

End Sub 

Répondre

3

Soit Commençons par le nettoyage qui un peu:

Public Sub Main() 

    Const Component_Name As String = "Updating TableA Data" 
    Const Conn_String As String = "Data Source=DB_A;Initial Catalog=TableA;Integrated Security=SSPI;" 

    Const sql_Emp As String = _ 
      "UPDATE TableA" _ 
      + " SET Contract = c.License_No, SEIN = convert(varchar, c.Lic_Exp_Date, 101)" _ 
     + " FROM Server.DB_B.dbo.TableB c" _ 
     + " INNER JOIN TableA b" _ 
      + " ON rtrim(ltrim(c.business_lic)) = rtrim(ltrim(cast(b.Account_Key as varchar(14))))" _ 
     + " WHERE c.Lic_Exp_Date= (" _ 
      + " SELECT MAX(Lic_Exp_Date)" _ 
      + " FROM Server.DB_B.dbo.TableB" _ 
      + " WHERE rtrim(ltrim(business_lic)) = rtrim(ltrim(cast(b.Account_Key as varchar(14))))" _ 
      + ") AND convert(varchar, c.Lic_Exp_Date, 101) <> convert(varchar, b.SEIN, 101)" 

    Try 
     Using con As New SqlConnection(Conn_String), _ 
       cmds New SqlCommand(sql_Emp, con) 

      Dts.Log("Opening DB Connection: " & con.ConnectionString, 0, Nothing) 

      con.Open() 
      cmd.ExecuteNonQuery() 

      Dts.Log(String.Format(Component_Name), 0, Nothing) 
      Dts.Events.FireInformation(0, Component_Name, String.Format("TableA Data Updating"), "", 0, True) 
      Dts.TaskResult = Dts.Results.Success 
     End Using 

    Catch ex As Exception 
     Dts.Events.FireError(0, Component_Name, ex.Message, "", 0) 
     Dts.Log("Exception detected: " & ex.ToString, 0, Nothing) 
     Dts.TaskResult = Results.Failure 

    End Try 

End Sub 

Bon, maintenant que je peux lire, je peux commencer à regarder ce qui pourrait être rompu. Revenez dans quelques minutes pour les modifications.


Bon, maintenant regardons cette requête. Il me manque des informations sur le type de données, donc je vais faire quelques suppositions. Veuillez corriger les erreurs éventuelles:

  • b.Account_Key est un type de nombre, probablement int. Sinon, vous auriez pas besoin de convertir en varchar
  • Les colonnes de Lic_Exp_Date sont vraiment de type datetime

Si ceux-ci sont corrects, je pense que cela va faire ce que vous voulez, mais faire un beaucoup plus vite:

UPDATE TableA 
    SET Contract = c1.License_No, SEIN = DATEADD(dd,0, DATEDIFF(dd,0, c1.Lic_Exp_Date)) 
FROM TableA b 
INNER JOIN Server.DB_B.dbo.TableB c1 
    ON ISNUMERIC(c1.busines_lic) = 1 AND cast(c1.business_lic AS int) = b.Account_Key 
INNER JOIN 
    (
     SELECT business_lic, MAX(Lic_Exp_Date) AS Lic_Exp_Date 
     FROM Server.DB_B.dbo.TableB 
     GROUP BY business_lic, License_No 
    ) c2 ON c2.business_lic = c1.business_lic AND c1.Lic_Exp_Date=c2.Lic_Exp_Date 
WHERE DATEADD(dd,0, DATEDIFF(dd,0, c1.Lic_Exp_Date)) <> DATEADD(dd,0, DATEDIFF(dd,0, b.SEIN)) 

Voilà ce qui a changé:

  • Tourner la sous-requête corrélée à une jointure. Une jointure sera beaucoup plus rapide, mais l'optimiseur de requêtes a peut-être déjà fait cela pour vous
  • Élimine le besoin d'appeler un certain nombre de fonctions par ligne - devrait également vous aider à mieux faire correspondre les index.
  • Utilisez une comparaison entière plutôt que chaîne pour votre principale rejoindre
  • fonctions de date d'utilisation plutôt que de convertir les chaînes pour retirer la partie du temps, ce qui devrait être beaucoup plus rapide et à son tour, me permettre de:
  • comparaisons de dates d'utilisation plutôt que les comparaisons de chaînes dans votre jointure
+0

@Joel Coehoorn: WOW! Cela FUME totalement comment je le faisais !!! Vous êtes un SQL Ninja! Merci! J'apprécie aussi beaucoup les notes en bas. Vous avez non seulement mis en place avec la réponse, mais aussi m'a donné l'information pour rendre mes futures requêtes/mises à jour plus rapides en me renseignant. Vous êtes vraiment une bonne personne! – JFV

+0

Pouvez-vous partager des temps difficiles pour les deux versions? Je suis curieux de savoir quel genre d'amélioration. –

+0

Il a fallu environ 2 minutes et 20 secondes avec mon code d'origine. Maintenant, cela prend 3 secondes. Merci! – JFV

2

La meilleure façon serait une tâche d'exécution SQL.

+0

@John Saunders: Vous avez raison d'utiliser l'option 'Execute SQL Task' au lieu de 'Script Task'. Cela a rendu mon code existant complet sans l'erreur de timeout. +1 pour l'aide – JFV

Questions connexes