Vous n'êtes pas identifié(e).

#1 21/12/2015 15:57:11

Papychampi
Membre

Faire un select avec un tableau

Bonjour,

Je dois faire un select avec toutes les valeurs d'un tableau passé en paramètre d'une procédure stocké. Actuellement je passe par:

DECLARE
	_ret				BOOLEAN;
	_save_quantity		INTEGER;
	_prev_quantity		INTEGER;
	_my_variable		INTEGER;
	_sorderid			INTEGER;
	_ptypeid			INTEGER;
	_batch			INTEGER;
	_sdeliveryid_new	INTEGER;
	_dddd			INTEGER;
	_pid				INTEGER;
	_save			INTEGER;
	_family			TEXT;
	_hex				TEXT;
BEGIN
	_ret:=check_sn(_sn);

	IF _ret = false
	THEN
		RETURN FALSE;
	END IF;
	RAISE LOG '======================================================================';
	/* Chercher la candence avec le numéro de série */
	IF (_id ISNULL)
	THEN
		IF (_sn ISNULL)
		THEN
			RAISE EXCEPTION 'Merci de rentrer une cadence ou un numéro de série';
		END IF;
		SELECT sdeliveryid FROM product WHERE sn = _sn INTO _id;
		IF (_id ISNULL)
		THEN
			RAISE EXCEPTION 'Aucun produit ne correspond à ce numéro de série';
		END IF;
	ELSE
		SELECT sdeliveryid FROM supplierdeliveries WHERE sdeliveryid = _id INTO _id;
		IF (_id ISNULL)
		THEN
			RAISE EXCEPTION 'Aucune cadence trouvée';
		END IF;
	END IF;

	/* Sélection de la quantité pour vérification */
	
	RAISE LOG 'sn_tab --> %', _sn_tab;
	RAISE LOG 'sn_tab_nb --> %', _sn_tab_nb;
	_save_quantity = _quantity;
	SELECT quantity FROM supplierdeliveries WHERE sdeliveryid = _id INTO _prev_quantity;
	RAISE LOG 'sdeliveryid --> %', _id;
	IF (_prev_quantity > _quantity)
	THEN
		IF (_sn_tab ISNULL OR _sn_tab_nb = 0 OR _sn_tab_nb != (_prev_quantity - _quantity))
		THEN
			RAISE EXCEPTION 'Merci de renseigner les numéros de série des cartes non reçues';
		END IF;
		
		SELECT COUNT(sn) FROM product WHERE sn IN (_sn_tab) AND sdeliverid = _id INTO _my_variable; // <--------------- _sn_tab est le problème

		IF (_my_variable != _sn_tab_nb)
		THEN
			RAISE EXCEPTION 'Le(s) numéro(s) de série ne correspond(ent) pas à la cadence indiquée';
		END IF;
	END IF;
	/* Vérification des quantités */
	IF _prev_quantity != _quantity
	THEN
		/* Création d'une nouvelle cadence pour absorber la différence de produit */
		SELECT sorderid FROM supplierdeliveries WHERE sdeliveryid = _id INTO _sorderid;
		SELECT ptypeid FROM supplierdeliveries WHERE sdeliveryid = _id INTO _ptypeid;
		SELECT batch FROM supplierdeliveries WHERE sdeliveryid = _id INTO _batch;
		INSERT INTO supplierdeliveries (sorderid, ptypeid, batch) VALUES (_sorderid, _ptypeid, _batch) RETURNING "sdeliveryid" INTO STRICT _sdeliveryid_new;

		IF _prev_quantity > _quantity /* Si on en a moins que prévu */
		THEN

			/* MAJ de la candence initiale */
			UPDATE supplierdeliveries SET quantity = _quantity WHERE  sdeliveryid = _id;
			/* MAJ de la nouvelle candence */
			UPDATE supplierdeliveries SET quantity = (_prev_quantity - _quantity) WHERE  sdeliveryid = _sdeliveryid_new;
			/* Changer status en carte jamais livré */
			UPDATE product SET sdeliveryid = _sdeliveryid_new, status = '00000000000000000000000000000101' WHERE sn IN (_sn_tab);
			
		ELSE /* Si on en a plus que prévu */

			/* MAJ de la nouvelle candence */
			UPDATE supplierdeliveries SET quantity = (_quantity - _prev_quantity), date = _date , deliveryslip = _deliveryslip WHERE  sdeliveryid = _sdeliveryid_new;
			SELECT ptypeid FROM product WHERE sn = _sn INTO _ptypeid;
			SELECT family FROM product_types WHERE ptypeid = _ptypeid INTO _family;
			SELECT max(hex_to_int(right( sn, 4))) FROM product WHERE ptypeid IN (SELECT ptypeid AS _ptypeidtab FROM product_types WHERE family = _family) INTO  _dddd;
			
			/* Création des nouveaux produits associés à la nouvelle cadence Date = date de livraison et status = carte comandé + carte livrée */
			FOR i IN 1 .. (_quantity - _prev_quantity) LOOP
				_dddd := _dddd + i;
				_hex = right('0000' || int_to_hex(_dddd),4);
				_sn := left(_sn, -4) || UPPER(_hex);
				
				/* Insertion */
				INSERT INTO product (sdeliveryid, ptypeid, sn, status, date) VALUES (_id, _ptypeid::integer, _sn::text, '00000000000000000000000000000011', _stardate);
			END LOOP;
		END IF;
	END IF;

	UPDATE product SET status = '00000000000000000000000000000011', date = _date WHERE sdeliveryid = _id;
	RAISE LOG 'sdeliveryid --> %', _id;
	UPDATE supplierdeliveries SET date = _date, deliveryslip = _deliveryslip WHERE  sdeliveryid = _id;
	/* Cloture de la commande */
	SELECT sorderid FROM supplierdeliveries WHERE sdeliveryid = _id INTO _pid;
	
	SELECT sdeliveryid FROM supplierdeliveries WHERE date ISNULL AND sorderid = _pid INTO _save;

	IF (_save ISNULL)
	THEN
		UPDATE supplierorders SET enddate = _date WHERE sorderid = _pid;
	END IF;
	RETURN TRUE;
END;
    _sn_tab text[],
    _sn_tab_nb integer,
    _sn text,
    _date date,
    _deliveryslip integer,
    _quantity integer,
    _id integer DEFAULT 0)
  RETURNS boolean AS

Donc du coup je voudrais savoirsi il existe un moyen de faire ça et si oui comment faire... Merci beaucoup d'avance pour les réponses

Cordialement

Papychampi

Hors ligne

#2 21/12/2015 20:14:13

rjuju
Administrateur

Re : Faire un select avec un tableau

Je pense que vous cherchez l'opérateur ANY. cf http://docs.postgresql.fr/9.3/functions-subquery.html

Par exemple

select * from generate_series(1,10) i where i = any( '{1,4}'::int[]);
 i 
═══
 1
 4
(2 rows)

Hors ligne

#3 22/12/2015 10:48:07

Papychampi
Membre

Re : Faire un select avec un tableau

Bonjour,

Merci de votre réponse.

Cependant le problème persiste. Enfin pas au point de me sortir une erreur non voulu mais le:

SELECT COUNT(sn) FROM product WHERE sdeliveryid = _id AND sn = ANY(_sn_tab) INTO _my_variable;

me retourne 0. Du coup j'ai quand même vérifié si mes valeur étaient bien dans mon tableau et elles y sont ensuite j'ai vérifié si celà ne venais pas du sdeliveryid mais apparemment non... Je me sens tellement près du but!

Cordialement,

Hors ligne

#4 22/12/2015 15:12:34

rjuju
Administrateur

Re : Faire un select avec un tableau

Que vous renvoie la requête si vous l'exécutez manuellement ? Par exemple

SELECT * FROM product WHERE sdeliveryid = le_id AND sn = ANY(le_tableau)

Hors ligne

#5 22/12/2015 16:54:01

Papychampi
Membre

Re : Faire un select avec un tableau

So...
J'ai fais un test en mode manuel... et je pense que le problème ne viens en effet pas du SQL mais bien du PHP puisque ça marche en manuel...

Du coup juste pour être sûr... J'ai une fonction php qui est censé transformé mes tableaux php en tableaux postgresql dont voici le code:

<?php
function to_pg_array($set) {
    settype($set, 'array'); // can be called with a scalar or array
    $result = array();
    foreach ($set as $t) {
        if (is_array($t)) {
            $result[] = to_pg_array($t);
        } else {
            $t = str_replace('"', '\\"', $t); // escape double quote
            if (! is_numeric($t)) // quote only non-numeric values
                $t = '"' . $t . '"';
            $result[] = $t;
        }
    }
    return '{' . implode(",", $result) . '}'; // format
}
?>

Est ce que ce bout de code serait à l'origine de mes problèmes?

Hors ligne

#6 22/12/2015 21:30:19

rjuju
Administrateur

Re : Faire un select avec un tableau

La fonction me semble fonctionner normalement, mais je ne suis pas du tout expert php. Du côté de la procédure stockée, pouvez-vous afficher le contenu de la variable ? par exemple raise notice '% % %', _sn_tab, _sn_tab[1], array_upper(_sn_tab[1]);

Hors ligne

#7 23/12/2015 10:42:41

Papychampi
Membre

Re : Faire un select avec un tableau

Bonjour,
Donc j'ai fait ce que tu m'a demandé sauf pour le array_upper parce que ça ne marche pas sur les tableau de text:

{"{\"TOTO#1552EA101__0029
\",\"TOTO#1552EA101__002A\"}"}

{"TOTO#1552EA101__0029
","TOTO#1552EA101__002A"} 

Du coup on observe un truc assez interessant on dirait un tableau double dimensions... Puis que quand on regarde bien le deuxième tableau à un bon affichage... hmmm... Celà voudrais dire que le tableau créé par cette fonction serait donc un tableau à deux dimenssions...

Dernière modification par Papychampi (23/12/2015 10:42:58)

Hors ligne

Pied de page des forums