Welcome to Sign in | Help
in Search

o problema de update

Last post 02-19-2008, 4:11 PM by Gherry. 7 replies.
Sort Posts: Previous Next
  •  07-30-2007, 5:18 PM 2346

    o problema de update

    am un tabel cu 5 coloane (id, c1, c2, c3, c4) cu urmatoarele inregistrari

    id       C1 C2 C3 C4
    --------------------------
    1        o    x          a

    2        o    x    g    c

    3        o    x    g     

     

    care trebuie adus la forma:

    id       C1 C2 C3 C4
    --------------------------
    1        o    x          a

    2        o    x          b

    3        o    x          c

    coloanele C1,2,3 sunt la fel iar C4 contine caractere in ordine plecand de la "a" (pt fiecare set de recorduri - sunt mai multe seturi diferite in tabel cu C1,2,3 identice si C4 = a,b,...)

    exista si o cheie compusa care contine toate coloanele deci nu pot avea 2 recorduri la fel

     

    am scris o functie care o apelez pt fiecare inregistrare si care stie sa verifice daca are forma corecta si, eventual sa corecteze in asa fel incat sa indeplineasca conditiile. (practi r2 si r3 trebuie corectate)

    daca rulez functia pe rand pt fiecare record merge corect insa daca o rulez pe tot setul imi zice ca se creaza inregistrari duplicate.. banuiesc ca asta e din cauza ca ruleaza in paralel pt r2 si r3 si amandoua se opresc la litera "b" in loc sa mearga una pana la "c" (aveti idee cum as putea verifica teoria asta)

     
    o solutie ar fi sa creez un cursor care sa parcurga tot tabelul si sa aplice functia pe rand fiecarui record dar as prefera sa evit asta asa ca: stie cineva o varianta mai eleganta?
     

    Filed under: ,
  •  07-30-2007, 7:44 PM 2348 in reply to 2346

    Re: o problema de update

    Incearca:

    DECLARE @tmp TABLE(id tinyint IDENTITY(1, 1), col1 varchar(10))
    INSERT INTO @tmp VALUES('a')
    INSERT INTO @tmp VALUES('b')
    INSERT INTO @tmp VALUES('c')
    INSERT INTO @tmp VALUES('d')............etc......

     UPDATE Table1 SET c3 = NULL, c4 = tmp.col1
    FROM Table1 t1 JOIN @tmp tmp ON t1.id = tmp.id

    *Table1 este tabelul  (id, c1, c2, c3, c4)

     

  •  07-31-2007, 9:47 AM 2349 in reply to 2348

    Re: o problema de update

    Smile nu m-am exprimat foarte clar (in exemplul dat am pus doar un set de inregistrari). in T1 am seturi de inregistrari care au primele 3 coloane la fel in cadrul setului (dar difera de la iun set la altul) iar C4 pleaca de la "a" pt fiecare set in parte iar id-urile sunt amestecate (deci intre inregistrari din cadrul unui set exisa inregisrtatri din multe alte seturi). Adica tabelul arata cam asa:

     

    id       C1 C2 C3 C4
    --------------------------
    23        o    x          a

    25        /     &    ^   

    40        /     &    ^
     
    44        <    >         a

    47        o    x    g   

    48        /     &         c

    49        o    x    g    c

    88        <    >   ?  

     deci aici am pus 3 seturi care se intrepatrund si au numar diferit de recorduri  

                /     &         c         - 3 records,

               o    x    g     c         - 3 records
     

               <    >   ?                - 2 records

     asa ca banuiesc ca o solutie ar presupune in primul rand un group by dupa primele 3 coloane, un tabel care sa contina literele de la a la z.. si cateva legaturi mai complexe.. (zic eu..) Smile

     deocamdata am facut cursorul si o sa lucrez cu el (pt ca momentan viteza de rezolvare e mai importanta decat calitatea solutiei) dar m-ar interesa foarte mult daca se poate face folosind procesarea paralela.. totusi suntem in sql Stick out tongue
     

  •  07-31-2007, 11:10 AM 2351 in reply to 2349

    Re: o problema de update

    Exprimare deficitara.
    Cand vei reusi sa ai exprimare clara, poate atunci vei obtine o solutie ...

    Cateva observatii se impun:
    [1] se utilizeaza termenul de câmp (sau atribut) si nu cel de coloana,
    [2] termenul de record (en.) are un echivalent in limba romana: inregistrare,
    [3] formularea "coloanele C1,2,3 sunt la fel" este neclara. Din ce punct de vedere sunt "la fel": din punct de vedere al tipului, al marimii, al domeniului ?
    [4] folosesti expresia "cheie compusa" care este o exprimare imprecisa deoarece atat o cheie primara, o cheie externa cat si o cheie candidat pot fi "chei compuse" (din context se poate deduce ca este vorba de o cheie primara compusa),
    [5] specifica cel putin versiunea SQL Server utilizata,

    Devil exprima-te CLAR. 

  •  07-31-2007, 12:37 PM 2353 in reply to 2351

    Re: o problema de update

    in primul rand recunosc ca exprimarea mea are lacune, motiv pt care am si scris un mesaj in care intrebam daca poate recomanda cineva niste cursuri de incepatori.. lucrez de vreo 3 ani in sql insa cam tot ce stiu am invatat din experiente proprii si mai putin din dialoguri cu alte persoane asa ca la capitolul terminologie stau extrem de rau pt ca pe mine m-a interesat utilitate si nu numele Stick out tongueSmile (plus ca 90% din documentatie era in engleza si acolo este termenul de column, record si constrain de aici unele erori de exprimare/traducere) deci apreciez enorm orice fel de critici pe chestia asta si mai ales sugestiile

     acum o sa incerc sa reformulez problema  Smile

    baza in cauza este pe SQL Server 2000 insa eu scriu toate query-urile si ruleze testele pe SQL Server 2005 Standard Edition dupa care le transfer pe 2000 deci trebuie sa lucreze pe ambele

     (am copiat baza de pe calculatorul clientului la mine si acum scriu query-urile care sa rezolve problema si le testez la mine iar cand sunt gata le voi rula pe baza clientului, deci nu exista transfer de date intre cele 2 baze)

    - am un tabel T1 din care 5 campuri sunt esentiale pt problema mea:  id, C1, C2, C3, C4

    - id este cheia primara

    - compania care a implementat baza a pus un index unic format din C1-4 (nu stiu cat e de corecta exprimarea) care ma impiedica sa am in tabel inreistrarile 2,q,w,e,r si 3,q,w,e,r (ele au cheia primara diferita insa combinatia C1-4 este identica)

     - inregistrarile din tabel se pot grupa in seturi (asta e de fapt o observatie, un fel de "busines rule" a beneficiarului)

    Problema este ca, in timp, benficiarul nu a avut o modalitate consecventa de introducere a datelor iar acum s-a ajuns la concluzia ca baza are o multime de inregistrari care in realitate sunt una si aceasi chestie insa in baza apar ca mai multe entitati scrise diferit asa ca s-a decis sa se aduca toate inregistrarile la o forma comuna in care C1-2 contin datele esentiale iar in cazul in care  avem mai multe inregistrari  care la care combinatia C1-2 este identica (ceea ce se intampla in foarte multe cazuri) vom folosi C4 pt a face diferenta si pt a respecta indexul de care ziceam. campul C3 va ramne gol (asta probabil ca suna aberant insa acolo sunt mai multe detalii in care nu are sens sa intru asa ca pt a simplifica problema consideram ca avem C3 gol in tot tabelul)

    Deci eu trebuie sa sterg ce este pe campul C3 iar apoi sa iau grupurile de inregistrari care au combinatia C1-2 identica si sa scriu un carcater pe C4 care sa diferentieze inregistrarile

     Am scris functia care imi returneaza caracteruul de care am nevoie pt fiecare inregistrare in parte in conformitate cu cerintele beneficiarului si functioneaza corect cand este folosita intr-un cursor care ia pe rand fiecare inregistrare din tabel insa daca incerc sa o rulez direct pe toate inregistrarile imi da eroare care zice ca incalc indexul unic format din C1-4 asa ca am presupus ca e din cauza ca functia este apelata pe 2 inregistrari din acelasi set in acelasi timp si, din cauza asta, returneaza acelasi rezultat pt C4.

     

  •  07-31-2007, 5:11 PM 2354 in reply to 2353

    Re: o problema de update

    Citat

    "Am scris functia care imi returneaza caracteruul de care am nevoie pt fiecare inregistrare in parte in conformitate cu cerintele beneficiarului si functioneaza corect cand este folosita intr-un cursor care ia pe rand fiecare inregistrare din tabel insa daca incerc sa o rulez direct pe toate inregistrarile imi da eroare ..."

     Asa cum ai zis si tu eroarea apare pt. ca modifici valorile din campul C4 (asa cel putin am inteles din ce ai scris in mesajul anterior), aceste modificari ducând la apariţia unor valori duplicat in indexul care admite doar VALORI UNICE C1+C2+C3+C4.

     
    Pentru a evita aceasta eroare poti proceda astfel:

    ALTER TABLE Tabel ALTER COLUMN c3 VARCHAR(36)
    UPDATE Tabel SET c3 = newid()

    ... aici rulezi scriptul tau pentru toate inregistrarile ...

    UPDATE Tabel SET c3 = NULL

     Explicatii:

    [1] Poti utiliza câmpul C3 într-un mod util dacă tot urmează să "ştergi" valorile acestui camp. Astfel defineşti C3 (de exemplu) de tip VARCHAR cu o dimensiune de 36 de caractere pentru a putea stoca GUIDuri. Valorile tip GUID au proprietatea de a fi unice cel puţin la nivelul aceluiaşi sistem de calcul/calculator (teoretic).

    Având valori UNICE în campul C3 atunci ÎN MOD DIRECT indexul cu valori UNICE C1+C2+C3+C4 va avea perechi de valori (C1+C2+C3+C4) UNICE. Ca atare, orice valori vei avea in C4 indexul va respecta în permanenţă restricţia de a avea valori unice(mai corect perechi de valori pentru ca este un index compus şi nu un index simplu) CREATE UNIQUE INDEX ...

    [2] Incarci GUIDuri unice in C3 din tabela.

    [3] Rulezi script-ul scris de tine

    [4] "Ştergi" valorile (mai precis GUIDurile) din câmpul C3 cu ajutorul unei comenzi UPDATE ... C3 = NULL

     

     

  •  07-31-2007, 8:00 PM 2357 in reply to 2354

    Re: o problema de update

    trebuie sa mai fac niste teste si o sa revin cu detalii oricum solutia suna superb Smile o sa te tin la curent

     

  •  02-19-2008, 4:11 PM 4094 in reply to 2346

    Re: o problema de update

    am revenit..

    in primul rand trebuie neaparat mentionez ca m-a luat cu dureri de cap incercand sa inteleg ce am sris eu in descrierea problemei asa ca mltumesc nespus celor care au rezistat tentatiei de a trece mai departe si au incercat sa ma ajute;

    in al doilea rand am reusit sa gasec inca un raspuns la problema mea si am decis sa il postez aici (fara prea multe explicatii pt ca nu ma pricep la alea)

    asta ar fi tabelul de test:

    CREATE TABLE [dbo].[Table_1](
        [id] [int] IDENTITY(1,1) NOT NULL,
        [sub_id] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
     CONSTRAINT [PK_Table_1] PRIMARY KEY CLUSTERED
    (
        [id] ASC
    )WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
    ) ON [PRIMARY]

    ------------------------------------------------------------------------------------------------------------------------
    acestea sunt datele de plecare (daca poate sa imi spuna cineva cum sa scriptez continutul unui tabel ar fi super) - dar se vede mai bine ce e nevoie in rezultate

    1a
    2a
    3ab
    4b
    5cdf
    6dfds
    7ddd
    8cdf
    9adf
    10dfds
    11bb
    12cc
    13ddd
    14ddd
    NULLNULL

    ------------------------------------------------------------------------------------------------------------------------
    acestea sunt rezultatele:

    1a1
    2a2
    3ab1
    9adf1
    4b1
    11bb1
    12cc1
    5cdf1
    8cdf2
    7ddd1
    13ddd2
    14ddd3
    6dfds1
    10dfds2
    NULLNULLNULL

    se poate observa ca am daugat o noua coloana care itroduce un fel de sub_id care incepe de la 1 in cazul fiecarui grup de inregistrari duplicate si incrementeaza pana la sfarsitul grupului.

    eu aveam nevoie de un query care sa imi genereze datele de pe acea coloana folosind ce se gasea in primele 2 coloane (prima era un id unic pe tabel)

    bineinteles ca aceasta este o reprezentare mult simplificata a problemei mele (inca o data imi cer scuze ca nu am dat un exemplu atat de clar de la inceput) si cred ca este irelevant motivul pt care ar vrea cineva sa faca ce am prezentat mai sus

    iar o rezolvare destul de interesanta la care am ajuns de curand cu mult ajutor din partea unui prieten ar fi urmatoarea:


    SELECT     id, SUBSTRING(sub_id, 1, 10) AS init, SUBSTRING(CAST
                              ((SELECT     COUNT(sub_id) + 1 AS Expr1
                                  FROM         Table_1 AS t2
                                  WHERE     (Table_1.id > id) AND (Table_1.sub_id = sub_id)) AS nvarchar(10)) + sub_id, 1, 1) AS result
    FROM         Table_1
    ORDER BY init, result


    daca poate sa imi spuna cineva care solutie este mai performanta (aceasta care foloseste COUNT sau cea in care se foloseste un cursor) m-ar scuti de testele care ar merita facute. Smile
    sau macar sa imi dati cateva linii care ar trebui urmarite pt un astfel de test, thx.
View as RSS news feed in XML
Powered by Community Server (Commercial Edition), by Telligent Systems