Information ausblenden
Willkommen im Forum für alle Datenbanken! Registriere Dich kostenlos und diskutiere über DBs wie Mysql, MariaDB, Oracle, Sql-Server, Postgres, Access uvm

Zeilenweises Durchlaufen einer SELECT-Anweisung

Dieses Thema im Forum "Microsoft SQL Server" wurde erstellt von mindhunter, 1 Oktober 2014.

  1. mindhunter

    mindhunter Benutzer

    Hallo,

    in einer Microsoft SQL Datenbank gibt es eine Tabelle, welche mit Parametern geändert werden soll. Als Beispiel habe ich ein Script, das diese Tabelle anlegt. Mit einer SELECT-Anweisung hole ich bestimmte Daten. Nun möchte ich diesen SELECT Zeile für Zeile durchlaufen und Werte neu setzten und mir die geänderten Daten in einem SELECT wieder anzeigen lassen, bzw. ausgeben. Z.B. wenn site_id = 3 dann schreibe in Test ‘blabla‘, site_id = 5 dann ‘bliblablup‘ in Test. Die Anzahl der Zeilen erfasse ich mit SELECT COUNT(*) FROM DUAL oder ist die FETCH-Anweisung dafür besser geeignet?

    Vielen Dank für eure Hilfe
    Stefan



    ---
    Code:
    DROP TABLE DUAL
     
    CREATE TABLE DUAL
    (
        site_id [int] NULL,
        Name [nchar](50) NULL,
        Abk [nchar](10) NULL,
        Cur [nchar](10) NULL,
        Class [nchar](10) NULL,
        Product [nchar](10) NULL,
        Project [nchar](10) NULL,
        Color_ID [nchar](10) NULL,
        Test [nchar](10) NULL
    )
     
     
    INSERT INTO DUAL (site_id, Name, Abk, Cur, Class, Product, Project, Color_ID, Test)
    VALUES (0,'0','NULL','EUR','NULL','NULL','NULL','NULL','NULL')
     
    INSERT INTO DUAL (site_id, Name, Abk, Cur, Class, Product, Project, Color_ID, Test)
    VALUES (1,'BU SC','BU SC','EUR','BU','NULL','NULL','0','NULL')
     
    INSERT INTO DUAL (site_id, Name, Abk, Cur, Class, Product, Project, Color_ID, Test)
    VALUES (2,'CI','NULL','EUR','BS','NULL','NULL','6','NULL')
     
    INSERT INTO DUAL (site_id, Name, Abk, Cur, Class, Product, Project, Color_ID, Test)
    VALUES (3,'PA','NULL','EUR','BS','NULL','NULL','78','NULL')
     
    INSERT INTO DUAL (site_id, Name, Abk, Cur, Class, Product, Project, Color_ID, Test)
    VALUES (4,'PI','NULL','EUR','BS','NULL','NULL','30','NULL')
     
    INSERT INTO DUAL (site_id, Name, Abk, Cur, Class, Product, Project, Color_ID, Test)
    VALUES (5,'PP','NULL','EUR','BS','NULL','NULL','42','NULL')
     
    INSERT INTO DUAL (site_id, Name, Abk, Cur, Class, Product, Project, Color_ID, Test)
    VALUES (6,'CI (HQ)','NULL','EUR','Site','NULL','NULL','7','NULL')
     
    INSERT INTO DUAL (site_id, Name, Abk, Cur, Class, Product, Project, Color_ID, Test)
    VALUES (7,'MF-K (PI)','NULL','EUR','Site','NULL','NULL','31','NULL')
     
    INSERT INTO DUAL (site_id, Name, Abk, Cur, Class, Product, Project, Color_ID, Test)
    VALUES (8,'Concord','NULL','EUR','Site','NULL','NULL','5','NULL')
     
    INSERT INTO DUAL (site_id, Name, Abk, Cur, Class, Product, Project, Color_ID, Test)
    VALUES (10,'Houston','NULL','EUR','Site','NULL','NULL','79','NULL')
     
    INSERT INTO DUAL (site_id, Name, Abk, Cur, Class, Product, Project, Color_ID, Test)
    VALUES (11,'Singapore','NULL','EUR','Site','NULL','NULL','77','NULL')
     
    SELECT site_id, Name, Abk, Cur, Class, Product, Project, Color_ID, Test  FROM DUAL WHERE Class = 'BS'
     
     
     
    DECLARE @numRow int
    DECLARE row_cursor CURSOR FOR
    SELECT site_id, Color_ID, Test FROM DUAL WHERE Class ='BS';
     
    SET @numRow =  (SELECT COUNT(*) FROM DUAL)
     
    OPEN row_cursor;
    FETCH NEXT FROM row_cursor;
     
    WHILE @@FETCH_STATUS = 0
        BEGIN
     
        -- site_id = 3 dann schreibe in Test  ‘bla_bla‘, site_id = 5 dann ‘bli_bla_blup‘ in Test.
        -- SELECT site_id, Color_ID, Test FROM DUAL...
     
        FETCH NEXT FROM row_cursor
        END
     
    CLOSE row_cursor;
    DEALLOCATE row_cursor;
     
    T_Pettbörg gefällt das.
  2. akretschmer

    akretschmer Datenbank-Guru

    SQL in Schleifen ist fast immer ganz schlecht. Wo kommen denn die Daten her? Aus einer anderen Tabelle?

    Angenommen, Du hast 2 Tabellen, mindhunter1 und 2, erstere soll geändert werden mit den Daten aus 2. Dazu dienst übrigens UPDATE. Also, Du hast:

    Code:
    test=# create table mindhunter1(id int, val int);
    CREATE TABLE   
    Time: 267,314 ms   
    test=*# insert into mindhunter1 select s, null from generate_series(1,10) s;
    INSERT 0 10   
    Time: 0,933 ms   
    test=*# select * from mindhunter1 ;   
     id | val   
    ----+-----   
      1 |   
      2 |   
      3 |
      4 |
      5 |
      6 |
      7 |
      8 |
      9 |
     10 |
    (10 rows)
    
    Time: 0,262 ms
    test=*# create table mindhunter2(id int, val int);
    CREATE TABLE
    Time: 20,248 ms
    test=*# insert into mindhunter2 values (3,5);
    INSERT 0 1
    Time: 0,322 ms
    test=*# insert into mindhunter2 values (8,15);
    INSERT 0 1
    Time: 0,127 ms
    
    Soweit klar, oder?

    Code:
    test=*# update mindhunter1 set val=mindhunter2.val from mindhunter2 where mindhunter1.id=mindhunter2.id;
    UPDATE 2
    Time: 0,485 ms
    test=*# select * from mindhunter1;
     id | val
    ----+-----
      1 |
      2 |
      4 |
      5 |
      6 |
      7 |
      9 |
     10 |
      3 |  5
      8 |  15
    (10 rows)
    
    Time: 0,147 ms
    
    Ist jetzt PostgreSQL, geht aber mit M$SQL ganz sicher auch so.
     
  3. mindhunter

    mindhunter Benutzer

    Die Daten kommen aus einer anderen Tabelle oder aus Eingabefeldern aus einer Web-Anwendung. Ich jetzt noch nicht klar. Ich wollte sehen und versethen, wie eine Schleife funktioniert.
     
  4. akretschmer

    akretschmer Datenbank-Guru

    Wie gesagt: Schleifen auf Mengen von Daten, also in Datenbanken, sind fast immer ganz übel. Das geht mit wenigen Datensätzen, wenn Du richtige Tabellen mit Millionen Rows hast fliegt es Dir um die Ohren.
     
  5. ukulele

    ukulele Datenbank-Guru

    Es gibt mehrere Wege, der Verzicht auf Schleifen ist sicher immer zu empfehlen. In deinem Fall könnte ein JOIN im UPDATE Befehl hilfreich sein (siehe akretschmers Join) und dir die Daten passend liefern. Auch eine CASE Anweisung kann innerhalb von UPDATE nützlich sein.

    Du kannst auch ganz ohne CURSOR abreiten, z.B. mit einer WHILE Schleife. Bietet aber glaube ich keinen Geschwindigkeitsvorteil.
     
  6. mindhunter

    mindhunter Benutzer

    Vielen Dank für die Antworten.

    @ukulele Könntest du mir bitte in mein Beispiel eine While-Schleife einbauen und wie man ganz ohne CURSOR arbeiten kann.
     
  7. ukulele

    ukulele Datenbank-Guru

    Code:
    DECLARE @counter INT,
            @pk UNIQUEIDENTIFIER
    
    SET        @counter = (    SELECT    count(1)
                            FROM    tabelle )
    
    WHILE    @counter > 0
    BEGIN
        SET        @pk = (    SELECT    pk
                        FROM (    SELECT    TOP (@counter) pk,
                                        ROW_NUMBER() OVER (ORDER BY pk) AS zeilennr
                                FROM    tabelle
                                ORDER BY pk ) x
                        WHERE    x.zeilennr = @counter )
    
        -- Aktion
    
        SET        @counter = @counter - 1
    END
     
Die Seite wird geladen...

Diese Seite empfehlen

  1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies.
    Information ausblenden