Création d'un numéro chrono dans ue procédure

Résolu
NHenry Messages postés 15112 Date d'inscription vendredi 14 mars 2003 Statut Modérateur Dernière intervention 13 avril 2024 - 8 mai 2012 à 15:01
NHenry Messages postés 15112 Date d'inscription vendredi 14 mars 2003 Statut Modérateur Dernière intervention 13 avril 2024 - 14 mai 2012 à 21:02
Bonjour,

Dans le cadre d'un projet, je dois générer un numéro chronologique à certains enregistrements.

Ces enregistrements peuvent avoir plusieurs numéro chronologiques.

Données sources :
DateId, référence vers la date de l'évènement
ResId, référence vers la réservation
ChronoNum, numéro chronologique (unique pour chaque date)

Une date peut avoir plusieurs réservations qui elles-mêmes peuvent avoir plusieurs numéro chrono (si plusieurs places réservées).

Ce que je voudrais faire, c'est une procédure stockée qui accepterais en paramètre :
L'Id de la date
L'Id de la résa
Le nombre de numéro chrono à générer

Les numéros auto-incrémentés ne sont exploitable ici, car les numéros chrono doivent être unique ET consécutif pour chaque date (Départ à 1).

Mon souci est qu'apparemment, on ne peux pas faire d'INSERT de données venant de la même table, voici 2 versions que j'ai essayé :
CREATE PROCEDURE InsertChrono(pDateId INT, pResSubId INT, pNb INT)
BEGIN
WHILE pNb > 0 DO
INSERT INTO ReservationChrono 
(ChronoDate, ChronoRes, ChronoNum) 
VALUES 
(
pDateId, pResSubId, 
(
SELECT MAX(ChronoNum)+1 
FROM ReservationChrono 
WHERE ChronoDate=pDateId
)
);
SET pNb = pNb - 1;
END WHILE;
END


CREATE PROCEDURE InsertChrono(pDateId INT, pResSubId INT, pNb INT)
BEGIN
WHILE pNb > 0 DO
INSERT INTO ReservationChrono 
(ChronoDate, ChronoRes, ChronoNum) 
VALUES 
(SELECT pDateId, pResSubId, MAX(ChronoNum)+1 
FROM ReservationChrono 
WHERE ChronoDate=pDateId)
);
SET pNb = pNb - 1;
END WHILE;
END


L'erreur est toujours vers le SELECT.

Je pensais que j'avais une solution, mais apparemment, non.
Auriez-vous des conseils, des techniques à utiliser, ou autre aide afin de remplir la fonction désirée ?

Je précise que je ne maitrise pas cette partie de SQL, je me contente le plus souvent des instructions de base.

Merci d'avance.

5 réponses

cs_jopop Messages postés 1540 Date d'inscription lundi 26 mai 2003 Statut Membre Dernière intervention 1 août 2013 12
10 mai 2012 à 15:19
Salut,

pour résumer :
* l'archi c'est :
DATE <--1,n-- RESA <--1,n-- CHRONO
* et tu cherches à initialiser n CHRONO pour une DATE et une RESA donnée
j'ai bon ?

Ce que je comprends pas trop c'est le coup du MAX :
- si tu n'as encore aucun CHRONO pour cette DATE/RESA, ça renverra null,
- tu cherches le MAX mais ensuite tu décrémentes ton compteur.

Bon, quoi qu'il en soit : un INSERT SELECT ne doit pas contenir de VALUES.
INSERT INTO table1 (champ1)
SELECT champ1 FROM table2;
3
cs_jopop Messages postés 1540 Date d'inscription lundi 26 mai 2003 Statut Membre Dernière intervention 1 août 2013 12
14 mai 2012 à 09:37
Re,

donc déjà un souci de moins (INSERT SELECT sans VALUES).

Sinon je suis allé revoir les de la proc stock sur le SDZ. On peut noter deux trucs dans ce doc :
- les assignations se font avec l'opérateur ":=",
- il est possible de changer de délimiteur (perso j'ai eu des soucis de scripts qui passaient pas avec le délimiteur ';' sur la commande 'mysql source'), à voir si c'est utile dans ton cas. A voir.

Sinon j'ai testé ça qui fonctionne sous TOAD :
CREATE FUNCTION maFunc(iMonParam INT) RETURNS INT
BEGIN
  DECLARE iMaLocal INT;
  SET iMaLocal := 10 + iMonParam;
  RETURN iMaLocal;
END;

SELECT maFunc(10);

A noter que pour vérifier le bon fonctionnement j'en ai fait une fonction, ce qui apporte quelques différences :
- le RETURNS pour le type de retour, le RETURN pour le retour,
- pas de "sens" au paramètre (IN, OUT ou INOUT)
Sinon c'est tout pareil. Je pense donc que ton souci est l'opérateur d'assignation.
3
NHenry Messages postés 15112 Date d'inscription vendredi 14 mars 2003 Statut Modérateur Dernière intervention 13 avril 2024 159
14 mai 2012 à 21:02
Bonjour,

Merci avec tes conseils, j'ai changé le délimiteur, voici le code fonctionnel pour ceux que ça intéresse :
DELIMITER |
CREATE PROCEDURE InsertChrono(pDateId INT, pResSubId INT, pNb INT)
BEGIN
WHILE pNb > 0 DO
INSERT INTO ReservationChrono 
(ChronoDate, ChronoRes, ChronoNum) 
SELECT pDateId, pResSubId, IFNULL(MAX(ChronoNum)+1 ,1)
FROM ReservationChrono 
WHERE ChronoDate=pDateId;
SET pNb := pNb - 1;
END WHILE;
END


Je n'ai pas vu ce tutoriel durant mes recherches, mais j'avoue que je n'aurais pas cherché du côté du délimiteur.

Parfois en informatique, il ne faut pas chercher à comprendre ...

---------------------------------------------------------------------
[list=ordered][*]Pour poser correctement une question et optimiser vos chances d'obtenir des réponses, pensez à lire le règlement CS, celui-ci pour bien poser votre question ou encore celui-ci pour les PFE et autres exercices[*]Quand vous postez un code, merci d'utiliser la coloration syntaxique (3ième icône en partant de la droite : )
[*]En VB.NET pensez à activer Option Explicit et Option Strict (propriété du projet) et à retirer l'import automatique de l'espace de nom Microsoft.VisualVasic (onglet Références dans les propriétés du projet).
[*]Si votre problème est résolu (et uniquement si c'est le cas), pensez à mettre "Réponse acceptée" sur le ou les messages qui vous ont aidés./list
---
3
NHenry Messages postés 15112 Date d'inscription vendredi 14 mars 2003 Statut Modérateur Dernière intervention 13 avril 2024 159
10 mai 2012 à 19:57
Bonjour,

"* l'archi c'est :
DATE <--1,n-- RESA <--1,n-- CHRONO "
En effet, c'est bien ça.

"et tu cherches à initialiser n CHRONO pour une DATE et une RESA donnée "
Oui, mais un numéro unique pour une date, pour la réservation (enfin pour une place, une résa contenant plusieurs places).

Donc en plus clair :
Date <- 1,n - Résa <- 1,n - Place <- 1,1 - Chrono

Et donc, je cherche à obtenir un numéro unique pour la date, identifiant la place.
Ce numéro est unique, sans trou et commence à 1 pour chaque date.
Donc pour plusieurs dates, je peux avoir le même numéro chrono, mais dans une date, je n'ai aucun doublon.

Concernant le MAX et la décrémentation, c'est pour générer respectivement un numéro consécutif pour une date et pour générer autant de numéro qu'il y a de place (un FOR en somme).

J'espère avoir été clair.

---------------------------------------------------------------------
[list=ordered][*]Pour poser correctement une question et optimiser vos chances d'obtenir des réponses, pensez à lire le règlement CS, celui-ci pour bien poser votre question ou encore celui-ci pour les PFE et autres exercices[*]Quand vous postez un code, merci d'utiliser la coloration syntaxique (3ième icône en partant de la droite : )
[*]En VB.NET pensez à activer Option Explicit et Option Strict (propriété du projet) et à retirer l'import automatique de l'espace de nom Microsoft.VisualVasic (onglet Références dans les propriétés du projet).
[*]Si votre problème est résolu (et uniquement si c'est le cas), pensez à mettre "Réponse acceptée" sur le ou les messages qui vous ont aidés./list
---
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
NHenry Messages postés 15112 Date d'inscription vendredi 14 mars 2003 Statut Modérateur Dernière intervention 13 avril 2024 159
12 mai 2012 à 17:07
Bonjour,

Après quelques tentatives, j'ai fais fonctionner :
INSERT INTO ReservationChrono 
(ChronoDate, ChronoRes, ChronoNum) 
SELECT 1, 1, IFNULL(MAX(ChronoNum)+1,1)
FROM ReservationChrono 
WHERE ChronoDate=1;


Mais ma procédure ne passe toujours pas :
CREATE PROCEDURE InsertChrono(pDateId INT, pResSubId INT, pNb INT)
BEGIN
WHILE pNb > 0 DO
INSERT INTO ReservationChrono 
(ChronoDate, ChronoRes, ChronoNum) 
SELECT pDateId, pResSubId, IFNULL(MAX(ChronoNum)+1 ,1)
FROM ReservationChrono 
WHERE ChronoDate=pDateId;
SET pNb = pNb - 1;
END WHILE;
END

#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 8
Soit la ligne de
WHERE ChronoDate=pDateId;

Sinon, j'ai aussi essayé :
CREATE PROCEDURE InsertChrono(IN pDateId INT, IN pResSubId INT, IN pNb INT)
BEGIN
DECLARE lCounter INT;
SET lCounter=0;
WHILE lCounter < pNb DO
INSERT INTO ReservationChrono 
(ChronoDate, ChronoRes, ChronoNum) 
SELECT pDateId, pResSubId, IFNULL(MAX(ChronoNum)+1 ,1)
FROM ReservationChrono 
WHERE ChronoDate=pDateId;
SET lCounter = lCounter + 1;
END WHILE;
END

#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 3
Soit sur le DECLARE ...

Je ne comprend pas pourquoi, avez-vous une idée ?
Apparemment, c'est un MySql 5.0.

Je continue de chercher.

---------------------------------------------------------------------
[list=ordered][*]Pour poser correctement une question et optimiser vos chances d'obtenir des réponses, pensez à lire le règlement CS, celui-ci pour bien poser votre question ou encore celui-ci pour les PFE et autres exercices[*]Quand vous postez un code, merci d'utiliser la coloration syntaxique (3ième icône en partant de la droite : )
[*]En VB.NET pensez à activer Option Explicit et Option Strict (propriété du projet) et à retirer l'import automatique de l'espace de nom Microsoft.VisualVasic (onglet Références dans les propriétés du projet).
[*]Si votre problème est résolu (et uniquement si c'est le cas), pensez à mettre "Réponse acceptée" sur le ou les messages qui vous ont aidés./list
---
0
Rejoignez-nous