2010-10-01 3 views
1

Je souhaite lire EmpID dans EMP Tableau basé sur certaines conditions. Pour chaque EmpID j'ai besoin de faire une opération dans une autre table. Comment puis-je lire la valeur unique de EmpID à la fois.Fonctionnalité de type tableau dans SQL Server 2008

Merci à l'avance

+2

Pouvez-vous expliquer "certaines opérations"? – Andomar

+0

Il y a 2 flèches à côté de chaque réponse. Si vous aimez la réponse, si c'est un peu utile, c'est une bonne pratique de cliquer sur le bouton up (upvote), et si la réponse est totalement fausse, vous pourriez la rétrograder, bien que les gens n'aiment pas, et vous aussi perdez la réputation points. Si votre question a reçu une réponse correcte, vous DEVEZ la marquer comme telle (le signe de vérification vert sous les flèches à côté de la réponse).C'est une «responsabilité» qui vient avec le droit de poser une question. Si vous ne le faites pas, les gens seront moins désireux de vous aider dans le futur. – AlexanderMP

Répondre

0

essayez de ne jamais boucler, travaillez sur des ensembles de données.

Vous pouvez insérer, mettre à jour, supprimer plusieurs lignes à la fois. ici dans un exemple insérer de plusieurs lignes:

INSERT INTO YourTable 
     (col1, col2, col3, col4) 
    SELECT 
     cola, colb+Colz, colc, @X 
     FROM .... 
      LEFT OUTER JOIN ... 
     WHERE... 

vous pouvez même insérer dans plusieurs tables en une seule instruction:

INSERT INTO YourTable 
     (col1, col2, col3, col4) 
     OUTPUT INSERTED.PK, Inserted.Col2 
      INTO OtherTable (ColA, ColB) 
    SELECT 
     cola, colb+Colz, colc, @X 
     FROM .... 
      LEFT OUTER JOIN ... 
     WHERE... 

Lorsque l'on regarde une boucle voir ce qu'il fait à l'intérieur. S'il s'agit simplement d'insertions/suppressions/mises à jour, réécrivez pour utiliser des commandes uniques. S'il y a des IF, voyez s'il peut s'agir d'instructions CASE ou de conditions WHERE sur inserts/deletes/updates. Si c'est le cas, supprimez la boucle et utilisez les commandes set.

J'ai pris des boucles et les ai remplacées par les commandes basées sur l'ensemble et réduit le temps d'exécution de quelques minutes à quelques secondes. J'ai pris des procédures avec de nombreuses boucles imbriquées et des appels de procédure et j'ai gardé les boucles (impossible d'utiliser seulement des insertions/suppressions/mises à jour), mais j'ai enlevé le curseur, et j'ai vu moins de blocage/blocage. Voici deux méthodes de mise en boucle qui sont mieux que les boucles curseur ...

si vous avez en boucle, sur un ensemble faire quelque chose comme ceci:

--this looks up each row for every iteration 
DECLARE @msg VARCHAR(250) 
DECLARE @hostname sysname 

--first select of currsor free loop 
SELECT @hostname= min(RTRIM(hostname)) 
    FROM master.dbo.sysprocesses (NOLOCK) 
    WHERE hostname <> '' 

WHILE @hostname is not null 
BEGIN 
    --just some example of some odd task that requires a loop 
    set @msg='exec master.dbo.xp_cmdshell "net send ' 
     + RTRIM(@hostname) + ' ' 
     + 'testing "' 
    print @msg 
    --EXEC (@msg) --<<will not actually send the messages 

    --next select of cursor free loop 
    SELECT @hostname= min(RTRIM(hostname)) 
     FROM master.dbo.sysprocesses (NOLOCK) 
     WHERE hostname <> '' 
     and hostname > @hostname 
END 

si vous avez un ensemble raisonnable d'articles (non 100 000) pour faire une boucle, vous pouvez le faire:

--this will capture each Key to loop over 
DECLARE @msg VARCHAR(250) 
DECLARE @From int 
DECLARE @To  int 
CREATE TABLE #Rows --use a table @variable depending on the number of rows to handle 
(
    RowID  int not null primary key identity(1,1) 
    ,hostname varchar(100) 
) 

INSERT INTO #Rows 
SELECT DISTINCT hostname 
    FROM master.dbo.sysprocesses (NOLOCK) 
    WHERE hostname <> '' 
SELECT @From=0,@[email protected]@ROWCOUNT 

WHILE @From<@To 
BEGIN 
    SET @[email protected]+1 

    --just some example of some odd task that requires a loop 
    SELECT @msg='exec master.dbo.xp_cmdshell "net send ' 
     + RTRIM(hostname) + ' ' 
     + 'testing "' 
     FROM #Rows 
     WHERE [email protected] 
    print @msg 
    --EXEC (@msg) --<<will not actually send the messages 
END 
+0

Merci beaucoup. – sreekanth

1
UPDATE otherTable... 
WHERE table2.EmpID IN (SELECT EMP.EmpID FROM EMP WHERE ...) 
+4

Si vous postez du code ou du code XML, ** veuillez ** surligner ces lignes dans l'éditeur de texte et cliquez sur le bouton "code" (101 010) dans la barre d'outils de l'éditeur pour le mettre en valeur! –

+0

Merci beaucoup. – sreekanth

0

En général, vous devriez éviter le code de procédure dans SQL, mais si vous avez vraiment besoin, utilisez les touches fléchées:

DECLARE myCursor CURSOR FAST_FORWARD 
FOR 
    SELECT --your SQL query, a regular SQL query. 
     field1, 
     field2 
    FROM 
     table 

OPEN myCursor; 
FETCH NEXT FROM myCursor 
INTO 
    @var1, --must be pre-declared, of the same types as field1 
    @var2 

WHILE (@@FETCH_STATUS = 0) 
BEGIN 


    --your code use @var1, @var2. Perform queries, do whatever you like. 
    --It will loop through every row fetched by the query in the beginning of the code, and perform this. 


    FETCH NEXT FROM myCursor --do this exactly as before the WHILE loop 
    INTO 
     @var1, 
     @var2 
END 
CLOSE myCursor 
+0

Thnak vous beaucoup pour votre réponse. En fait, je suis en train d'écrire dans les procédures, je n'ai pas implémenté les curseurs. – sreekanth

+0

Par "procédural", j'entendais itératif, code où vous fournissez des étapes, où vous décomposez la tâche en parties plus petites et définissez des séquences d'instructions. C'est en face de la syntaxe déclarative, qui est SQL (et beaucoup plus), où vous déclarez ce dont vous avez besoin, sans fournir d'instructions spécifiques sur la façon de le réaliser. – AlexanderMP

+0

Merci beaucoup. – sreekanth

0

En utilisant une approche basée ensemble à la logique SQL est toujours l'approche préférée. En ce sens, DanDan est une réponse acceptable. Vous pouvez également utiliser des curseurs SQL. Bien que les ressources soient lourdes, elles vous permettent de parcourir une série et d'appliquer une logique sur chaque ligne.

DECLARE @EMPID char(11) 

DECLARE c1 CURSOR READ_ONLY 
FOR 
SELECT EmpID 
FROM EMP 

OÙ * some_clause *

OPEN c1 

FETCH NEXT FROM c1 
INTO @EMPID 

WHILE @@FETCH_STATUS = 0 
BEGIN 

    PRINT @EMPID 

    FETCH NEXT FROM c1 
    INTO @EMPID 

END 

CLOSE c1 
DEALLOCATE c1 
+0

Merci beaucoup. – sreekanth

0

Faisant suite à DanDan's Answer, T-SQL vous permet de faire participer à la clause FROM d'une déclaration UPDATE (je ne sais plus si cela est ANSI ou ne pas). EG

UPDATE 
    OtherTable 
SET 
    Auditing = Employees.EmployeeName 
FROM 
    OtherTable 
    INNER JOIN 
     Employees ON OtherTable.EmpId = Employees.EmpId 
WHERE 
    Employees.DateStarted > '2010-09-01' 
+0

Merci beaucoup. – sreekanth