2009-10-21 11 views
9

Pracuję nad jakimś starszym kodem/bazą danych i muszę dodać pole do bazy danych, które będzie rejestrowało numer sekwencji powiązany z tym (obcym) identyfikatorem.MySQL: Dodaj kolumnę sekwencji opartą na innym polu

przykład dane tabeli (bieżący):

ID  ACCOUNT  some_other_stuff 
1  1   ... 
2  1   ... 
3  1   ... 
4  2   ... 
5  2   ... 
6  1   ... 

trzeba dodać kolumnę sequenceid inkrementacja oddzielnie dla każdego konta daje:

ID  ACCOUNT  SEQ  some_other_stuff 
1  1   1  ... 
2  1   2  ... 
3  1   3  ... 
4  2   1  ... 
5  2   2  ... 
6  1   4  ... 

Należy zauważyć, że sekwencja jest związana z rachunku.

Czy istnieje sposób, w jaki mogę to osiągnąć w SQL, czy też mogę użyć skryptu PHP, aby wykonać to zadanie dla mnie?

TIA, Kev

Odpowiedz

6

ten powinien działać, ale prawdopodobnie jest wolny:

CREATE temporary table seq (id int, seq int); 
INSERT INTO seq (id, seq) 
    SELECT id, 
     (SELECT count(*) + 1 FROM test c 
     WHERE c.id < test.id AND c.account = test.account) as seq 
    FROM test; 

UPDATE test INNER join seq ON test.id = seq.id SET test.seq = seq.seq; 

Zadzwoniłem do stołu "test"; oczywiście to musi być ustawione poprawnie. Musisz użyć tabeli tymczasowej, ponieważ MySQL nie pozwoli ci użyć podselekcji z tej samej tabeli, którą aktualizujesz.

+0

@tom haigh can proszę wyjaśnić, jak to działa? – FBP

4

Pytanie jest oznaczona jako "mysql", a więc tak, auto_increment MySQL może tworzyć GroupWise kolejne identyfikatory.
zobaczyć http://dev.mysql.com/doc/refman/5.0/en/example-auto-increment.html:

Dla MyISAM i BDB tabele można określić AUTO_INCREMENT na kolumnie wtórnym w indeksie wielokrotnego kolumny. W takim przypadku wygenerowana wartość kolumny AUTO_INCREMENT jest obliczana jako MAX(auto_increment_column) + 1 WHERE prefix=given-prefix. Jest to przydatne, gdy chcesz umieścić dane w uporządkowanych grupach.

edit: Przykładowy skrypt php (używając PDO, ale to ta sama gra z modułem php-mysql)

$pdo = new PDO('mysql:host=...;dbname=...', '...', '...'); 
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 

// example table 
$pdo->exec(
    'CREATE TEMPORARY TABLE Foo (
    id int auto_increment, 
    account int, 
    someotherstuff varchar(32), 
    primary key(account,id) 
) engine=MyIsam' 
); 
// insert example data 
$stmt = $pdo->prepare('INSERT INTO Foo (account,someotherstuff) VALUES (?,?)'); 
$stmt->execute(array(1, '1a')); 
$stmt->execute(array(1, '1b')); 
$stmt->execute(array(1, '1c')); 
$stmt->execute(array(2, '2a')); 
$stmt->execute(array(2, '2b')); 
$stmt->execute(array(1, '1d')); 
unset($stmt); 

// query data 
foreach($pdo->query('SELECT account,id,someotherstuff FROM Foo') as $row) { 
    echo $row['account'], ' ', $row['id'], ' ', $row['someotherstuff'], "\n"; 
} 

drukuje

1 1 1a 
1 2 1b 
1 3 1c 
2 1 2a 
2 2 2b 
1 4 1d 
+0

Dzięki za odpowiedź. Przepraszamy - powinienem mieć określone tabele są innoDB. W końcu poszedłem do poniższego rozwiązania tabel tymczasowych, ale doceniam dane wejściowe! Twoje zdrowie! –

+0

Ładne rozwiązanie. To jest poprawna odpowiedź. działa świetnie. – SuB

5

Tworzenie wyzwalacza:

CREATE TRIGGER trg_mytable_bi 
BEFORE INSERT ON mytable 
FOR EACH ROW 
BEGIN 
     DECLARE nseq INT; 
     SELECT COALESCE(MAX(seq), 0) + 1 
     INTO nseq 
     FROM mytable 
     WHERE account = NEW.account; 
     SET NEW.seq = nseq; 
END; 
+0

Zakładając, że OP ma MySQL 5 ... – Ben

+0

Dziękuję za odpowiedź, ale ostatecznie podjąłem powyższe rozwiązanie tabeli tymczasowej. –

+0

Dla każdego, kto ma problemy z pomyłkowymi błędami, zobacz tutaj o używaniu ograniczników w wyzwalaczu: http://stackoverflow.com/questions/5814153/error-in-your-sql-syntax-creating-mysql-trigger – Druckles

Powiązane problemy