2009-10-21 9 views
9

Je travaille sur un code/une base de données existant et je dois ajouter un champ à la base de données qui va enregistrer un numéro de séquence lié à cet ID (étranger).MySQL: Ajouter une colonne de séquence basée sur un autre champ

données de la table Exemple (courant):

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

je dois ajouter une colonne sequenceid qui incrémente séparément pour chaque compte, réalisation:

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

Notez que la séquence est liée à compte.

Y a-t-il un moyen de parvenir à cela en SQL, ou est-ce que j'ai recours à un script PHP pour faire le travail pour moi?

TIA, Kev

Répondre

6

Cette devrait fonctionner mais est probablement lent:

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; 

J'ai appelé la table 'test'; évidemment, cela doit être réglé correctement. Vous devez utiliser une table temporaire car MySQL ne vous permet pas d'utiliser une sous-sélection de la même table que celle que vous mettez à jour.

+0

@tom haigh can vous s'il vous plaît expliquer comment cela fonctionne? – FBP

4

La question est étiquetée comme "mysql", donc oui, la auto_increment de MySQL peut créer ids séquentielle groupwise.
voir http://dev.mysql.com/doc/refman/5.0/en/example-auto-increment.html:

Pour MyISAM et BDB tables vous pouvez spécifier AUTO_INCREMENT sur une colonne secondaire dans un index à colonnes multiples. Dans ce cas, la valeur générée pour la colonne AUTO_INCREMENT est calculée en tant que MAX(auto_increment_column) + 1 WHERE prefix=given-prefix. Ceci est utile lorsque vous voulez mettre des données dans des groupes ordonnés.

edit: exemple de script php (en utilisant PDO, mais il est le même jeu avec le module 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"; 
} 

impressions

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

Merci pour la réponse. Désolé - j'aurais dû préciser que les tables sont innoDB. Je suis finalement allé pour la solution de tables de temp ci-dessous, mais apprécie l'entrée! À votre santé! –

+0

Belle solution. C'est la bonne réponse. fonctionne très bien. – SuB

5

Créer un déclencheur:

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

En supposant que l'OP a MySQL 5 ... – Ben

+0

Merci pour votre réponse, mais à la fin je suis allé pour la solution de table temporaire ci-dessus. –

+0

Pour toute personne ayant des problèmes avec des erreurs confuses, voir ici à propos de l'utilisation des délimiteurs dans le déclencheur: http://stackoverflow.com/questions/5814153/error-in-your-sql-syntax-creating-mysql-trigger – Druckles

Questions connexes