Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1385 connectés 

 


 Mot :   Pseudo :  
 
 Page :   1  2  3
Page Suivante
Auteur Sujet :

aidez une pauvre etudiante avec une requete bloquante

n°913951
Moktar1er
No one replies...
Posté le 03-12-2004 à 15:09:28  profilanswer
 

Reprise du message précédent :

Arjuna a écrit :

J'ai pas parlé de les cumuler :heink:
 
J'ai dit que soit vous laissez tomber les transactions parceque ces threads ne sont pas critiques, soit vous forcez un commit après les lignes de la transaction qui font des locks emmerdant, quite à gérer la remise en l'état de la base de façon manuelle... Soit vous passez à un SGBD qui gère mieu les transactions (oubliez tout de suite SQL Server, qui le même problème, c'est pour cette raison que je sais exactement de quoi je parle, j'ai déjà été bloqué par ça).
 
Après, gizmo ou lorill, qui semble plus proche de la couche "DBA" des SGBD auront peut-être un mot-clé magique à vous fournir pour débloquer ça, mais j'en doute fortement (c'est tellement chiant comme limitation que ça serait déverrouillé par défaut si une méthode permettait de contourner)


 
pour le moment j'ai viré les contraintes d'intégrité référentielles, de toutes façons ce qu'on met dans les 2 tables qui posent problème, on va le chercher dans les autres tables jointes à coup de SELECT, donc la cohérence devrait être au rendez-vous...
ensuite, oui, on va creuser en espérant tomber sur le petit mot clé magique qui nous manque :jap:

mood
Publicité
Posté le 03-12-2004 à 15:09:28  profilanswer
 

n°913954
Arjuna
Aircraft Ident.: F-MBSD
Posté le 03-12-2004 à 15:10:57  profilanswer
 

moktar1er a écrit :

la même appli doit être lancée un nombre indéfini de fois sur le même serveur
une appli c'est un paquet de threads qui s'enchaînent
pour sécurité, les données ne sont validées qu'à la toute fin du traitement, on ne peut pas se permettre de les cummuler ou quoi que ce soit


Hmmmm. T'as peut-être butté sur cette phrase :
 
"Tu de démerdes pour sortir ton INSERT de la transaction histoire de faire un COMMIT immédiatement après et t'auras plus de problème."
 
En fait, tu fais pas deux threads ou je ne sais quoi pour gérer ça.
 
Juste que ton prog va faire grossomodo :
 

Code :
  1. BEGIN
  2.    INSERT INTO ...;
  3.    COMMIT;
  4.    BLABLA...
  5.    RE-BLABLA...
  6.    COMMIT;
  7. END;


 
Avec un COMMIT juste après le INSERT qui fait chier. (en espérant que vous avez un pas un INSERT toutes les deux lignes, parceque sinon vous n'êtes pas rendu :D
 
Et si les transactions vous pouvez vous en passer, je pense qu'il existe un mot clé style :
 
"SET AUTOCOMMIT OFF" qui permettra à PostGre de ne pas faire de transaction implicite, et à ce moment vous n'aurez plus ce problème, puisque les seuls transactions restantes seront les transactions atomique (1 seule instruction)

n°913973
Arjuna
Aircraft Ident.: F-MBSD
Posté le 03-12-2004 à 15:23:16  profilanswer
 

A noter que si vous devez obligatoirement pouvoir parralèliser les traîtements, à priori, les transactions ne sont pas obligatoires.
 
En effet, il faut savoir que si deux transactions tournent en //, alors une transaction A peut très bien se terminer après une transaction B, et en se basant sur des données mises à jour par B, alors que B a commencé après A, se basant sur des données mises à jour par A.
 
En bref. Imagine le programme (syntaxe T-SQL, j'ai plus l'habitude du PL/SQL) :
 

Code :
  1. BEGIN
  2.    SELECT @A = T1.VAL FROM T1 WHERE T1.ID = 1
  3.    SELECT @B = T2.VAL FROM T2 WHERE T2.ID = 1
  4.    UPDATE T1 SET VAL = @A+1 WHERE T1.ID = 1
  5.    UPDATE T2 SET VAL = @B + @A WHERE T2.ID = 1
  6. END


 
Déroule les deux algos à la main, en les faisant tourner l'un après l'autre, et en //.
Tu vas voir l'intérêt de locker les données modifiées durant une transaction. La version //isée est totalement déconnante.
 
Si tu tombe dans ce cas, Oracle est à ma connaissance la seule base à pouvoir supporter des transactions au niveau CHAMP (ou LIGNE, selon la config) et donc te permettra de //iser des transactions ne tapant pas sur les mêmes données.
Si tu ne tombes pas dans ce cas, alors laisse tomebr les transactions, elles te sont inutiles (remettre en l'état une base après une erreur, c'est pas très compliqué, surtout quand tu n'as pas de relations dans tous les sens.)  
En plus ce sera plus rapide, et tu auras par conséquent moins de threads à faire tourner en // ;)
 
PS: ceci dit, quelque soit ton SGBD, mon exemple sera dans tous les cas planté, car les deux permières lignes, qui sont la source du problème lié au chevauchement des process, ne feront jamais de lock ;) Il faut dans ce cas faire un LOCK manuel sur T1 et T2, mais c'est une autre histoire ;))


Message édité par Arjuna le 03-12-2004 à 15:25:41
n°913981
Arjuna
Aircraft Ident.: F-MBSD
Posté le 03-12-2004 à 15:26:35  profilanswer
 

... tiens, j'ai un doute... je crois que SQL Server fait un LOCK par défaut même pour un select quand on fait une transaction (c'est heureusement débrayable), mais c'est une autre histoire...


Message édité par Arjuna le 03-12-2004 à 15:29:06
n°913985
lorill
Posté le 03-12-2004 à 15:32:26  profilanswer
 

Arjuna a écrit :


Après, gizmo ou lorill, qui semble plus proche de la couche "DBA" des SGBD auront peut-être un mot-clé magique à vous fournir pour débloquer


euh [:joce]
 
les bases de données, c'est pas du tout mon truc, j'en suis qu'un simple utilisateur

n°913986
Arjuna
Aircraft Ident.: F-MBSD
Posté le 03-12-2004 à 15:32:38  profilanswer
 

Sinon, juste comme ça.
 
Voici la doc de SQL Server 2000 qui offre finalement quelques hints pour délocker un DELETE, INSERT, UPDATE ou SELECT.
 
Vu que le comportement "de base" de postgre est similaire à celui de SQL Server, avec beaucoup de chance, c'est le même système de hints pour l'empêcher de locker.
 

Citation :


 
 Référence de Transact-SQL  
 
 
INSERT
Ajoute une nouvelle ligne à une table ou une vue.
 
Syntaxe
INSERT [ INTO]  
    { table_name WITH ( < table_hint_limited > [ ...n ] )  
        | view_name  
        | rowset_function_limited  
    }  
 
    {    [ ( column_list ) ]  
        { VALUES  
            ( { DEFAULT | NULL | expression } [ ,...n] )  
            | derived_table  
            | execute_statement  
        }  
    }  
    | DEFAULT VALUES  
 
< table_hint_limited > ::=  
    { FASTFIRSTROW  
        | HOLDLOCK  
        | PAGLOCK  
        | READCOMMITTED  
        | REPEATABLEREAD  
        | ROWLOCK  
        | SERIALIZABLE  
        | TABLOCK  
        | TABLOCKX  
        | UPDLOCK  
    }  
 
Arguments
[INTO]  
 
Mot clé facultatif qui peut être inséré entre le mot clé INSERT et la table cible.
 
table_name
 
Nom d'une table ou d'une variable de table qui doit recevoir les données.  
 
WITH (<table_hint_limited> [...n])
 
Une ou plusieurs options de table autorisées pour une table cible. Le mot clé WITH et les parenthèses sont obligatoires. READPAST, NOLOCK et READUNCOMMITTED ne sont pas autorisés. Pour plus d'informations sur les indicateurs de table, voir FROM.
 
view_name
 
Nom et alias facultatif d'une vue. La vue dont la référence est view_name doit pouvoir être mise à jour. Les modifications apportées par l'instruction INSERT ne peuvent pas affecter plus d'une des tables de base référencées dans la clause FROM de la vue. Par exemple, une instruction INSERT dans une vue contenant plusieurs tables doit utiliser une column_list qui fait uniquement référence aux colonnes d'une seule table de base. Pour plus d'informations sur les vues pouvant être mises à jour, voir CREATE VIEW.  
 
rowset_function_limited
 
Fonction OPENQUERY ou OPENROWSET. Pour plus d'informations, voir OPENQUERY et OPENROWSET.  
 
(column_list)
 
Liste d'une ou de plusieurs colonnes dans lesquelles les données doivent être insérées. column_list doit être entre parenthèses et délimité par des virgules.  
 
Si une colonne ne se trouve pas dans column_list, Microsoft® SQL Server™ doit pouvoir fournir une valeur basée sur la définition de la colonne ; dans le cas contraire, il n'est pas possible de charger la ligne. SQL Server fournit automatiquement une valeur pour la colonne si :  
 
elle a une propriété IDENTITY, la valeur d'identité incrémentielle suivante est utilisée ;
 
 
elle a une valeur par défaut, la valeur par défaut de la colonne est utilisée ;
 
 
elle a un type de données timestamp, la valeur date/heure courante est utilisée ;
 
 
elle accepte les valeurs NULL, une valeur NULL est utilisée.  
column_list et la liste VALUES doivent être utilisées lors de l'insertion de valeurs explicites dans une colonne d'identité et l'option SET IDENTITY_INSERT doit avoir la valeur ON pour la table.
 
VALUES  
 
Introduit la liste des valeurs de données à insérer. Il doit y avoir une valeur de donnée pour chaque colonne de la liste column_list (si spécifiée) ou de la table. La liste des valeurs doit être entre parenthèses.
 
Si les valeurs de la liste VALUES ne sont pas dans le même ordre que les colonnes de la table ou n'ont pas de valeur pour chaque colonne de la table, column_list doit être utilisé afin de spécifier de manière explicite la colonne qui stocke chaque valeur entrante.
 
DEFAULT
 
Force SQL Server à charger la valeur par défaut définie pour une colonne. S'il n'existe pas de valeur par défaut pour la colonne et qu'elle admet les valeurs NULL, NULL sera insérée. Pour une colonne définie à l'aide du type de données timestamp, la valeur date/heure suivante est insérée. DEFAULT n'est pas valide pour une colonne d'identité.
 
expression
 
Constante, variable ou expression. L'expression ne peut pas contenir d'instruction SELECT ou EXECUTE.
 
derived_table
 
Toute instruction SELECT valide qui renvoie des lignes de données à charger dans la table.
 
execute_statement
 
Toute instruction EXECUTE valide qui renvoie des données avec les instructions SELECT ou READTEXT.
 
Si vous utilisez execute_statement avec INSERT, chaque jeu de résultats doit être compatible avec les colonnes de la table ou de column_list. execute_statement peut être utilisé pour exécuter des procédures stockées sur le même serveur ou sur un serveur distant. La procédure du serveur distant est exécutée et les jeux de résultats sont renvoyés au serveur local où ils sont chargés dans la table. Si execute_statement renvoie des données avec l'instruction READTEXT, chaque instruction READTEXT peut renvoyer un maximum de 1 mégaoctet de données (1024 Ko). execute_statement peut également être utilisé avec les procédures étendues et insère les données renvoyées par le thread principal de cette procédure étendue. Les sorties provenant de threads autres que le thread principal ne sont pas insérées.
 
 
 
Remarque  Pour SQL Server version 7.0, execute_statement ne peut pas contenir une procédure stockée étendue qui renvoie des colonnes de type text ou image. Il s'agit là d'une différence par rapport aux versions antérieures de SQL Server.
 
 
DEFAULT VALUES
 
Force la nouvelle ligne à prendre les valeurs par défaut définies pour chaque colonne.
 
Notes
INSERT ajoute de nouvelles lignes à une table. Pour remplacer des données dans une table, les instructions DELETE ou TRUNCATE TABLE doivent être utilisées pour supprimer les données existantes avant de charger de nouvelles données à l'aide de INSERT. Pour modifier des valeurs de colonne dans des lignes existantes, utilisez UPDATE. Pour créer une nouvelle table et y charger des données en une fois, utilisez l'option INTO de l'instruction SELECT.
 
Dans sa portée, la variable table est accessible de la même façon qu'une table normale. Ainsi, la variable table peut servir de table à laquelle des lignes doivent être ajoutées dans une instruction INSERT. Pour plus d'informations, voir table.
 
Un nom en quatre parties, dont la partie nom de serveur est établie à l'aide de la fonction OPENDATASOURCE, peut être utilisé en tant que source de table dans toutes les situations où un nom de table peut être inclus dans une instruction INSERT.
 
Les colonnes créées à l'aide du type de données uniqueidentifier stockent les valeurs de type binaire au format 16 octets. Contrairement à ce qui se passe avec les colonnes d'identité, SQL Server ne génère pas automatiquement des valeurs pour les colonnes comportant le type de données uniqueidentifier. Lors d'une opération d'insertion, les variables dont le type de données est uniqueidentifier et les constantes de chaînes au format xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (36 caractères y compris les tirets, x correspondant à un chiffre hexadécimal compris entre 0 et 9 ou a et f) peuvent être utilisées pour les colonnes uniqueidentifier. Par exemple, 6F9619FF-8B86-D011-B42D-00C04FC964FF est une valeur correcte pour une variable ou une colonne uniqueidentifier. Utilisez la fonction NEWID() afin d'obtenir un GUID (identificateur global unique).
 
Lorsque vous insérez des lignes, les règles suivantes sont appliquées :  
 
Si une valeur est chargée dans des colonnes de type char, varchar ou varbinary, le remplissage ou la troncature des espaces blancs de fin (espaces pour char et varchar, zéros pour varbinary) est déterminé par la valeur de SET ANSI_PADDING définie pour la colonne lors de la création de la table. Pour plus d'informations, voir SET ANSI_PADDING  
Ce tableau illustre l'opération par défaut lorsque SET ANSI_PADDING comporte la valeur OFF.
 
Type de données Opération par défaut  
Char Remplit la valeur par des espaces jusqu'à la largeur définie pour la colonne.  
Varchar Supprime les espaces de fin jusqu'au dernier caractère différent d'un espace ou jusqu'au dernier caractère d'espacement simple pour les chaînes composées uniquement d'espaces.  
Varbinary Supprime les zéros à droite.  
 
 
Si une chaîne vide (' ') est chargée dans une colonne de type varchar ou text, l'opération par défaut consiste à charger la chaîne de longueur zéro. Si le niveau de compatibilité de la base de données est inférieur à 70, la valeur est convertie en un espace simple. Pour plus d'informations, voir sp_dbcmptlevel.  
 
 
Si une instruction INSERT enfreint une contrainte ou une règle, ou si elle comprend une valeur incompatible avec le type de données de la colonne, l'instruction échoue et SQL Server affiche un message d'erreur.  
 
 
L'insertion d'une valeur NULL dans une colonne de type text ou image ne crée pas un pointeur de texte valide et ne prédéfinit pas une page texte de 8 Ko. Pour plus d'informations sur l'insertion de données text et image, voir Utilisation des fonctions text, ntext et image.  
 
 
Si INSERT charge plusieurs lignes à l'aide de SELECT ou EXECUTE, toute violation de règle ou de contrainte à partir des valeurs chargées met fin à l'instruction entière et aucune ligne n'est chargée.
 
 
Lorsque des valeurs sont insérées dans des tables SQL Server distantes et que certaines valeurs ne sont pas spécifiées pour toutes les colonnes, l'utilisateur doit identifier les colonnes pour lesquelles les valeurs spécifiées doivent être insérées.  
La valeur de l'option SET ROWCOUNT est ignorée pour les instructions INSERT portant sur les vues partitionnées locales et distantes. En outre, cette option n'est pas prise en charge pour les instructions INSERT portant sur les tables distantes sous SQL Server 2000 lorsque le niveau de compatibilité ascendante a pour valeur 80.
 
Lorsqu'un déclencheur INSTEAD-OF est défini sur les actions INSERT dans une table ou une vue, il est exécuté au lieu de l'instruction INSERT. Les versions antérieures de SQL Server ne prennent en charge que les déclencheurs AFTER définis sur les instructions INSERT et les autres instructions de modification des données.
 
Lorsqu'une instruction INSERT rencontre une erreur arithmétique (dépassement de capacité, de division par zéro ou erreur de domaine) lors de l'évaluation de l'expression, SQL Server gère ces erreurs comme si SET ARITHABORT était activée (valeur ON). Le reste du lot est annulé et un message d'erreur est renvoyé.
 
Autorisations
Les autorisations INSERT sont octroyées par défaut aux membres du rôle de serveur fixe sysadmin, aux membres des rôles de base de données fixes db_owner et db_datawriter, et au propriétaire de la table. Les membres des rôles sysadmin, db_owner et db_securityadmin, ainsi que le propriétaire de la table peuvent attribuer des autorisations aux autres utilisateurs.
 
Exemple
A. Utilisation d'une instruction INSERT simple
Cet exemple crée une table T1 et insère une ligne.
 
IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
      WHERE TABLE_NAME = 'T1')
   DROP TABLE T1
GO
CREATE TABLE T1 ( column_1 int, column_2 varchar(30))
INSERT T1 VALUES (1, 'Row #1')
 
B. Insertion de données qui ne sont pas dans le même ordre que les colonnes
Cet exemple utilise column_list et la liste VALUES afin de spécifier de manière explicite les valeurs insérées dans chaque colonne.
 
IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
      WHERE TABLE_NAME = 'T1')
   DROP TABLE T1
GO
CREATE TABLE T1 ( column_1 int, column_2 varchar(30))
INSERT T1 (column_2, column_1) VALUES ('Row #1',1)
 
C. Insertion de données de valeurs inférieures à celles des colonnes
Cet exemple crée une table avec quatre colonnes. Les instructions INSERT insèrent des lignes qui contiennent des valeurs de certaines colonnes mais pas de toutes.
 
IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
      WHERE TABLE_NAME = 'T1')
   DROP TABLE T1
GO
CREATE TABLE T1  
( column_1 int identity,  
  column_2 varchar(30)  
    CONSTRAINT default_name DEFAULT ('column default'),
  column_3 int NULL,
  column_4 varchar(40)
)
INSERT INTO T1 (column_4)  
   VALUES ('Explicit value')
INSERT INTO T1 (column_2,column_4)  
   VALUES ('Explicit value', 'Explicit value')
INSERT INTO T1 (column_2,column_3,column_4)  
   VALUES ('Explicit value',-44,'Explicit value')
SELECT *  
FROM T1
 
D. Chargement de données dans une table qui comprend une colonne d'identité
Les deux premières instructions INSERT acceptent la génération de valeurs d'identité pour les nouvelles lignes. La troisième instruction INSERT supplante la propriété IDENTITY de la colonne à l'aide de l'instruction SET IDENTITY_INSERT et insère une valeur explicite dans la colonne d'identité.
 
IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
      WHERE TABLE_NAME = 'T1')
   DROP TABLE T1
GO
CREATE TABLE T1 ( column_1 int IDENTITY, column_2 varchar(30))
INSERT T1 VALUES ('Row #1')
INSERT T1 (column_2) VALUES ('Row #2')
SET IDENTITY_INSERT T1 ON  
INSERT INTO T1 (column_1,column_2)  
   VALUES (-99,'Explicit identity value')
SELECT *  
FROM T1
 
E. Chargement de données dans une table via une vue
L'instruction INSERT de cet exemple spécifie un nom de vue. Cependant, la nouvelle ligne est insérée dans la table sous-jacente de la vue. L'ordre de la liste VALUES dans l'instruction INSERT doit correspondre à l'ordre des colonnes de la vue.
 
IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
      WHERE TABLE_NAME = 'T1')
   DROP TABLE T1
GO
IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.VIEWS
      WHERE TABLE_NAME = 'V1')
   DROP VIEW V1
GO
CREATE TABLE T1 ( column_1 int, column_2 varchar(30))
GO
CREATE VIEW V1 AS SELECT column_2, column_1  
FROM T1
GO
INSERT INTO V1  
   VALUES ('Row 1',1)
SELECT *  
FROM T1
 
F. Chargement de données à l'aide de l'option DEFAULT VALUES
L'instruction CREATE TABLE de cet exemple définit chaque colonne avec une valeur qui peut être utilisée lorsqu'aucune valeur explicite n'a été spécifiée dans l'instruction INSERT. L'option DEFAULT VALUES de l'instruction INSERT sert à ajouter des lignes sans fournir de valeurs explicites.
 
IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
      WHERE TABLE_NAME = 'T1')
   DROP TABLE T1
GO
CREATE DEFAULT bound_default AS 'Bound default value'
GO
CREATE TABLE T1  
( column_1 int identity,  
  column_2 varchar(30)  
    CONSTRAINT default_name DEFAULT ('column default'),
  column_3 timestamp,
  column_4 varchar(30),
  column_5 int NULL)
GO
USE master
EXEC sp_bindefault 'bound_default','T1.column_4'
INSERT INTO T1 DEFAULT VALUES  
SELECT *  
FROM T1
 
G. Chargement de données à l'aide des options SELECT et EXECUTE
Cet exemple illustre trois méthodes d'obtention des données d'une table et leur chargement dans une autre. Chaque méthode est basée sur une instruction SELECT multitable incluant une expression et une valeur littérale dans la liste des colonnes.
 
La première instruction INSERT utilise une instruction SELECT pour extraire directement les données de la table source (authors) et stocker le jeu de résultats dans la table author_sales. La seconde instruction INSERT exécute une procédure qui comprend l'instruction SELECT, et la troisième instruction INSERT exécute l'instruction SELECT comme une chaîne littérale.  
 
IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
      WHERE TABLE_NAME = 'author_sales')
   DROP TABLE author_sales
GO
IF EXISTS(SELECT name FROM sysobjects  
      WHERE name = 'get_author_sales' AND type = 'P')
   DROP PROCEDURE get_author_sales
GO
USE pubs
CREATE TABLE author_sales
( data_source   varchar(20),
  au_id         varchar(11),
  au_lname      varchar(40),
  sales_dollars smallmoney
)
GO
CREATE PROCEDURE get_author_sales  
AS  
   SELECT 'PROCEDURE', authors.au_id, authors.au_lname,  
      SUM(titles.price * sales.qty)  
   FROM authors INNER JOIN titleauthor  
      ON authors.au_id = titleauthor.au_id INNER JOIN titles
      ON titleauthor.title_id = titles.title_id INNER JOIN sales
      ON titles.title_id = sales.title_id
   WHERE authors.au_id like '8%'
   GROUP BY authors.au_id, authors.au_lname
GO
--INSERT...SELECT example
USE pubs
INSERT author_sales
   SELECT 'SELECT', authors.au_id, authors.au_lname,  
      SUM(titles.price * sales.qty)  
   FROM authors INNER JOIN titleauthor  
      ON authors.au_id = titleauthor.au_id INNER JOIN titles
      ON titleauthor.title_id = titles.title_id INNER JOIN sales
      ON titles.title_id = sales.title_id
   WHERE authors.au_id LIKE '8%'
   GROUP BY authors.au_id, authors.au_lname
 
--INSERT...EXECUTE procedure example
INSERT author_sales EXECUTE get_author_sales
 
--INSERT...EXECUTE('string') example
INSERT author_sales  
EXECUTE  
('
SELECT ''EXEC STRING'', authors.au_id, authors.au_lname,  
   SUM(titles.price * sales.qty)  
   FROM authors INNER JOIN titleauthor  
      ON authors.au_id = titleauthor.au_id INNER JOIN titles
      ON titleauthor.title_id = titles.title_id INNER JOIN sales
      ON titles.title_id = sales.title_id
   WHERE authors.au_id like ''8%''
   GROUP BY authors.au_id, authors.au_lname
')
 
--Show results.
SELECT * FROM author_sales
 
H. Insertion de données à l'aide de la clause TOP dans une instruction SELECT
Étant donné qu'une instruction SELECT peut être spécifiée dans une instruction INSERT, la clause TOP peut également être utilisée dans l'instruction SELECT. L'exemple insère les 10 premiers auteurs de la table authors dans une nouvelle table appelée new_authors.
 
IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
      WHERE TABLE_NAME = 'new_authors')
   DROP TABLE new_authors
GO
USE pubs
CREATE TABLE new_authors
(
 au_id    id,
 au_lname varchar(40),
 au_fname varchar(20),
 phone    char(12),
 address  varchar(40),
 city     varchar(20),    
 state    char(2),  
 zip         char(5),
 contract bit
)
INSERT INTO new_authors  
SELECT TOP 10 *  
FROM authors
 
 
Voir aussi
 
CREATE TABLE  
 
EXECUTE  
 
FROM
 
IDENTITY (Propriété)
 
NEWID
 
SELECT
 
SET ROWCOUNT
 
©1988-2000 Microsoft Corporation. Tous droits réservés.


 
Au mieu, ce sera la même syntaxe (faut pas trop rêver :p)
Avec un peu de chance, ça vous donnera une piste pour trouver les mots-clés de PostGre qui font la même chose (s'ils existent)


Message édité par Arjuna le 03-12-2004 à 15:32:48
n°913987
Arjuna
Aircraft Ident.: F-MBSD
Posté le 03-12-2004 à 15:33:05  profilanswer
 

lorill a écrit :

euh [:joce]
 
les bases de données, c'est pas du tout mon truc, j'en suis qu'un simple utilisateur


Ah, j'ai confusionné avec chaispuki alors :)

n°913989
Arjuna
Aircraft Ident.: F-MBSD
Posté le 03-12-2004 à 15:34:42  profilanswer
 

Arf, j'ai pas donné la bonne page de l'aide :D
 

Citation :


 
 Accès aux données relationnelles et modification  
 
 
Indicateurs de verrouillage
Plusieurs indicateurs de verrouillage au niveau des tables peuvent être spécifiés avec les instructions SELECT, INSERT, UPDATE, et DELETE pour indiquer à Microsoft® SQL Server™ 2000 le type de verrou à utiliser. Les indicateurs de verrouillage au niveau des tables peuvent être utilisés pour un contrôle plus fin des types de verrous acquis sur un objet. Ces options de verrouillage écrasent le niveau d'isolation courant de la transaction pour la session.
 
 
 
Remarque  L'optimiseur de requêtes SQL Server prend automatiquement la décision adéquate. Il est recommandé de n'utiliser les indicateurs de verrouillage au niveau des tables au lieu du verrouillage par défaut que si cela est nécessaire. La désactivation d'un niveau de verrouillage peut influer de manière négative sur la concurrence d'accès.
 
 
Indicateur de verrouillage Description  
HOLDLOCK Conserve un verrou partagé jusqu'à la fin de la transaction au lieu de libérer le verrou dès que la table, ligne ou page de données n'est plus requise. HOLDLOCK est l'équivalent de SÉRIALISABLE.  
NOLOCK N'émet pas de verrous partagés et n'effectue pas de verrous exclusifs. Lorsque cette option est activée, il est possible de lire une transaction non validée ou un jeu de pages annulé au milieu d'une lecture. Les lectures incorrectes sont possibles. S'applique uniquement à la commande SELECT.  
PAGLOCK Établit des verrous de page aux endroits où un simple verrou de table apparaît normalement.  
READCOMMITTED Effectue une recherche avec la même sémantique de verrouillage qu'une transaction à un niveau d'isolation LECTURE VALIDÉE. SQL Server 2000 fonctionne à ce niveau par défaut.  
READPAST Ignore les lignes verrouillées. Si cette option est spécifiée, la transaction ignore les lignes verrouillées par les autres transactions et qui devraient normalement figurer dans le jeu de résultats, au lieu de bloquer la transaction en attendant que les autres transactions aient libéré les verrous sur ces lignes. READPAST ne s'applique qu'aux transactions opérant au niveau LECTURE VALIDÉE et ne lit que les lignes au-dessus du verrou de ligne. Ne s'applique qu'à la commande SELECT.  
READUNCOMMITTED Équivalent à NOLOCK.  
REPEATABLEREAD Effectue une recherche avec la même sémantique de verrouillage qu'une transaction à un niveau d'isolation LECTURE RENOUVELABLE.  
ROWLOCK Utilise les verrous au niveau des lignes, au lieu des verrous au niveau des pages et des tables dont la granularité est moins fine.  
SERIALIZABLE Effectue une recherche avec la même sémantique de verrouillage qu'une transaction à un niveau d'isolation SÉRIALISABLE. Équivalent à HOLDLOCK.  
TABLOCK Utilise les verrous au niveau des tables, au lieu des verrous au niveau des pages et des lignes, dont la granularité est plus fine. SQL Server conserve ce verrou jusqu'à la fin de la commande. Si l'option HOLDLOCK est également spécifiée, le verrou est maintenu jusqu'à la fin de la transaction.  
TABLOCKX Utilise un verrou exclusif sur une table. Ce verrou empêche les autres de lire ou de mettre à jour la table et est conservé jusqu'à la fin de la commande ou transaction.  
UPDLOCK Utilise les verrous de mise à jour au lieu des verrous partagés durant la lecture de la table et les maintient jusqu'à la fin de l'instruction ou de la transaction. UPDLOCK a l'avantage de vous autoriser à lire les données (sans bloquer les autres lecteurs) et de les mettre à jour ultérieurement avec la certitude que les données n'ont pas été modifiées depuis que vous les avez lues.  
XLOCK Utilise un verrou exclusif qui sera maintenu jusqu'à la fin de la transaction sur toutes les données traitées par l'instruction. Ce verrou peut être spécifié avec PAGLOCK ou TABLOCK, auquel cas il s'applique au niveau de granularité approprié.  
 
 
Par exemple, si le niveau d'isolation d'une transaction est SERIALIZABLE et que l'indicateur de verrouillage NOLOCK au niveau des tables est utilisé avec l'instruction SELECT, les verrous d'étendues de clés habituellement utilisés pour assurer la mise en série ne sont pas appliqués.
 
USE pubs
GO
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
GO
BEGIN TRANSACTION
SELECT au_lname FROM authors WITH (NOLOCK)
GO
 
Les verrous générés sont :
 
EXEC sp_lock
GO
 
spid dbid ObjId indid Type Ressource Mode État  
1 1 0 0 DB   S GRANT  
6 1 0 0 DB   S GRANT  
7 1 0 0 DB   S GRANT  
8 4 0 0 DB   S GRANT  
8 4 0 0 DB   S GRANT  
8 4 117575457 0 TAB   Sch-S GRANT  
9 4 0 0 DB   S GRANT  
9 1 21575115 0 TAB   IS GRANT  
 
 
SELECT object_name(117575457)
GO
-----------------------------
authors
 
Le seul verrou appliqué faisant référence à authors est le verrou de stabilité de schéma (Sch-S). Dans ce cas, la possibilité de sérialisation n'est plus garantie.
 
 
Voir aussi
 
DELETE
 
INSERT
 
SELECT
 
SET TRANSACTION ISOLATION LEVEL
 
UPDATE
 
©1988-2000 Microsoft Corporation. Tous droits réservés.

n°913997
Lam's
Profil: bas.
Posté le 03-12-2004 à 15:38:37  profilanswer
 

Chuis ptetre con, mais la doc a l'air de dire que par défaut, il lock une page, mais que ROWLOCK lui fait locker les lignes seulement. C'est pas ce que tu reproches à SQL serveur de ne pas faire, justement ? (et je note que la doc a 4 ans).

n°913999
skeye
Posté le 03-12-2004 à 15:39:21  profilanswer
 


 

Arjuna a ensuite ajouté :

Arf, j'ai pas donné la bonne page de l'aide :D


 
[:rofl2]


Message édité par skeye le 03-12-2004 à 15:39:35

---------------
Can't buy what I want because it's free -
mood
Publicité
Posté le 03-12-2004 à 15:39:21  profilanswer
 

n°914020
gizmo
Posté le 03-12-2004 à 15:48:33  profilanswer
 

Arjuna, tu fais chier. Tu parles encore une fois sans savoir (pour changer). Pg ne lock pas systématiquement une table en écriture dans une transaction, il ne le fait que lorsqu'il y a des contraintes d'intégrité référentielle dessus. pour toutes les autres il ne fait un lock que sur les lignes.
 
Le problèmes des tables avec contraintes référentielle est nettement plus complexe que ce que ta petite explication laisse supposer. En effet, l'intérêt de bosser dans une transaction à ce niveau c'est que justement l'intégrité peut affecter l'ensemble de la table et il est impossible pour un SGDB de savoir à l'avance si on peut relacher des lignes sauf si l'utilisateur le demande explicitement. Or, pour le demander explicitement, il faut pouvoir utiliser les transactions imbriquées, ce qui ne sera supporté par PgSQL que dans la v8.0 qui devrait sortir d'ici un mois si tout va bien.
 
Bon, maintenant, soyons productif.
 
Vu votre version de SGBD, une des solutions que je vois pour vous serait de travailler dans tes tables temporaires. Ainsi, comme chaque transaction aurait sa table temporaire, vous n'aurez plus de lock et vous ne serez pas obliger de sortir quelque chose de la transaction ou de désactiver les références. Ainsi, à la fin des transaction, il suffirait de recopier le résultat des tables temporaires dans les tables principales, ce qui réduira le temps des lock. Maintenant, il faut voir si cette solution est possible avec le reste du traitement que vous avez à faire.

n°914072
Arjuna
Aircraft Ident.: F-MBSD
Posté le 03-12-2004 à 16:23:58  profilanswer
 

Lam's a écrit :

Chuis ptetre con, mais la doc a l'air de dire que par défaut, il lock une page, mais que ROWLOCK lui fait locker les lignes seulement. C'est pas ce que tu reproches à SQL serveur de ne pas faire, justement ? (et je note que la doc a 4 ans).


J'ai pas dit qu'on pouvait pas forcer SQL Server à pa locker.
Celà dit, je reproche à SQL Server de ne pas descendre au niveau CHAMP.
 
Si tu fais un :
 
UPDATE T1 SET C1 = VAL WHERE ID = 1
 
Alors tu peux pas faire sans risque ceci, tant que t'as pas commité (le "nolock" est inacceptable comme clause d'un select car bien trop dangereux) :
 
SELECT C2 FROM T1 WHERE ID = 1
 
Alors que pourtant T1.C2 n'est pas affecté par la transaction. Oracle permet de faire ça.
 
Ensuite, je sais pas si vous avez déjà testé SQL Server avec des ROWLOCK. Bah moi oui, et je peux vous dire que ça prends moins de temps de mettre en queue les transactions que de les sérialisées dans ces conditions. Le moteur n'est pas prévu pour bosser comme ça, un point c'est tout. Je vais pas vous faire un cours de SQL Server, je vous parle juste de mon expérience.
 
Windows sait faire du multi-processus, et pourtant on recommande sous Windows de faire du multi-thread, malgré ses points dangereux. Pourquoi ? Parceque Windows gère mal le multi-process. Ben là c'est pareil, je vais pas vous mentir en vous disant que SQL Server c'est génial pour faire du rowlock, il sait faire, mais ça s'arrête là.

n°914077
Arjuna
Aircraft Ident.: F-MBSD
Posté le 03-12-2004 à 16:27:25  profilanswer
 

gizmo a écrit :

Arjuna, tu fais chier. Tu parles encore une fois sans savoir (pour changer). Pg ne lock pas systématiquement une table en écriture dans une transaction, il ne le fait que lorsqu'il y a des contraintes d'intégrité référentielle dessus. pour toutes les autres il ne fait un lock que sur les lignes.
 
Le problèmes des tables avec contraintes référentielle est nettement plus complexe que ce que ta petite explication laisse supposer. En effet, l'intérêt de bosser dans une transaction à ce niveau c'est que justement l'intégrité peut affecter l'ensemble de la table et il est impossible pour un SGDB de savoir à l'avance si on peut relacher des lignes sauf si l'utilisateur le demande explicitement. Or, pour le demander explicitement, il faut pouvoir utiliser les transactions imbriquées, ce qui ne sera supporté par PgSQL que dans la v8.0 qui devrait sortir d'ici un mois si tout va bien.
 
Bon, maintenant, soyons productif.
 
Vu votre version de SGBD, une des solutions que je vois pour vous serait de travailler dans tes tables temporaires. Ainsi, comme chaque transaction aurait sa table temporaire, vous n'aurez plus de lock et vous ne serez pas obliger de sortir quelque chose de la transaction ou de désactiver les références. Ainsi, à la fin des transaction, il suffirait de recopier le résultat des tables temporaires dans les tables principales, ce qui réduira le temps des lock. Maintenant, il faut voir si cette solution est possible avec le reste du traitement que vous avez à faire.


Excuse-moi de te faire chier.
Mais j'ai du mal à concevoir que ton explication tienne la route étant donné que la requête posant problème porte sur un INSERT.
Je ne vois pas comment une ligne insérée dans une table, quelquesoit les relations portant sur cette table, peut en affacter les autres. Si tu parlais d'un DELETE ou un UPDATE, à la limite, mais pas d'un INSERT.
Ou alors donne-moi un exemple, parceque clairement, je n'arrive pas à en imaginer un (qui fasse intervenir des relations du moins)
 
 
Ah, et excuse-moi d'avoir indiqué que tu pourrais peut-être donner une meilleur solution à leur problème.
 
Excuse-moi aussi de ne pas être un crack de PG (oui, je ne l'ai jamais utilisé). Cela dit, je me base sur les problèmes que j'ai déjà eu avec d'autres produits et bizarrement, d'un outils à l'autre, on a très souvent des problèmes identiques et des solutions similaires. Maintenant, si t'es pas foutu de comprendre ça, alors dit-le tout de suite, je ne posterai plus une ligne dans cette section du forum.
 
Par contre, il ne vaudrait mieu pas pour toi que je tombe sur une question à laquelle je sais répondre et à laquelle tu n'as pas daigné répondre. Compris ?


Message édité par Arjuna le 03-12-2004 à 16:29:53
n°914130
gizmo
Posté le 03-12-2004 à 17:14:12  profilanswer
 

chrisbk > SET TRANSACTION ISOLATION LEVEL SERIALIZABLE ;)
arjuna > pas le temps de te répondre maintenant, je  ferai ca ce soir un un autre jour.

n°914133
skeye
Posté le 03-12-2004 à 17:15:09  profilanswer
 

gizmo a écrit :

chrisbk > SET TRANSACTION ISOLATION LEVEL SERIALIZABLE ;)


Il risquait pas de le trouver par hasard celui-là...[:joce]


---------------
Can't buy what I want because it's free -
n°914171
Arjuna
Aircraft Ident.: F-MBSD
Posté le 03-12-2004 à 17:42:52  profilanswer
 

skeye a écrit :

Il risquait pas de le trouver par hasard celui-là...[:joce]


Bah pourtant...
 

Citation :


 
 Référence de Transact-SQL  
 
 
SET TRANSACTION ISOLATION LEVEL
Contrôle le comportement par défaut du verrouillage de transaction de toutes les instructions SELECT de Microsoft® SQL Server™ émises par une connexion.
 
Syntaxe
SET TRANSACTION ISOLATION LEVEL  
    { READ COMMITTED  
        | READ UNCOMMITTED  
        | REPEATABLE READ  
        | SERIALIZABLE  
    }
 
Arguments
READ COMMITTED
 
Spécifie que les verrous partagés sont maintenus durant la lecture des données pour éviter des lectures incorrectes. Les données peuvent néanmoins être modifiées avant la fin de la transaction, ce qui produit des lectures non renouvelées ou des données fantômes. Cette option est définie par défaut dans SQL Server.
 
READ UNCOMMITTED
 
Implémente la lecture incorrecte, ou le verrouillage de niveau 0, ce qui signifie qu'aucun verrou partagé n'est généré et qu'aucun verrou exclusif n'est respecté. Lorsque cette option est activée, il est possible de lire des données non validées, ou incorrectes ; les valeurs des données peuvent être modifiées et des lignes peuvent apparaître ou disparaître dans le jeu de données avant la fin de la transaction. Cette option a le même effet que l'activation de l'option NOLOCK dans toutes les tables de toutes les instructions SELECT d'une transaction. Il s'agit du niveau d'isolation le moins restrictif parmi les quatre disponibles.
 
REPEATABLE READ
 
Des verrous sont placés dans toutes les données utilisées dans une requête, afin d'empêcher les autres utilisateurs de mettre à jour les données. Toutefois, un autre utilisateur peut ajouter des lignes fantômes à un jeu de données ; celles-ci seront incluses dans des lectures ultérieures dans la transaction courante. Utilisez cette option uniquement lorsque cela s'avère nécessaire, car la concurrence d'accès est inférieure au niveau d'isolation par défaut.
 
SERIALIZABLE
 
Place un verrou sur un jeu de données, empêchant les autres utilisateurs de mettre à jour les données ou d'insérer des lignes dans le jeu de données, jusqu'à la fin de la transaction. Il s'agit du niveau d'isolation le plus restrictif parmi les quatre niveaux disponibles. Utilisez cette option uniquement lorsque cela s'avère nécessaire, car la concurrence d'accès est moindre. Cette option a le même effet que l'utilisation de l'option HOLDLOCK dans toutes les tables de toutes les instructions SELECT d'une transaction.
 
Notes
Une seule option peut être utilisée à la fois, et elle reste en vigueur durant cette connexion, jusqu'à ce qu'elle soit explicitement modifiée. Cette option devient le comportement par défaut, sauf si une option d'optimisation est spécifiée au niveau de la table dans la clause FROM de l'instruction.
 
L'option SET TRANSACTION ISOLATION LEVEL est définie lors de l'exécution, et non pas durant l'analyse.
 
Exemple
Dans cet exemple, l'option TRANSACTION ISOLATION LEVEL est définie pour la session. Pour chaque instruction Transact-SQL suivante, SQL Server maintient tous les verrous partagés jusqu'à la fin de la transaction.
 
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ
GO
BEGIN TRANSACTION
SELECT * FROM publishers
SELECT * FROM authors
...
COMMIT TRANSACTION
 
 
Voir aussi
 
Optimisation des niveaux d'isolation des transactions
 
DBCC USEROPTIONS
 
Niveaux d'isolation
 
SELECT
 
SET
 
©1988-2000 Microsoft Corporation. Tous droits réservés.

n°914173
Arjuna
Aircraft Ident.: F-MBSD
Posté le 03-12-2004 à 17:43:21  profilanswer
 

C'est à se demander qui à pompé sur l'autre, ça donne vraiment l'impression qu'ils bossent ensemble ces deux là [:spamafote]

n°914175
Arjuna
Aircraft Ident.: F-MBSD
Posté le 03-12-2004 à 17:44:28  profilanswer
 

Ceci dit, Gizmo, si je comprends bien ce qui est écrit dans la doc SQL Server, et si PG se comporte pareil, "SERIALIZABLE" semble la dernière solution à adopter (:??:)
 
Si PG le supporte aussi, "REPEATABLE READ" me semble plus adapté.
 
PS: l'aide en ligne de SQL Server n'est pas à l'abri d'une erreur, ce ne serait pas le première fois que j'en trouve une.


Message édité par Arjuna le 03-12-2004 à 17:47:00
n°914234
chrisbk
-
Posté le 03-12-2004 à 19:42:33  profilanswer
 

Arjuna a écrit :

Bah pourtant...
 
[quote]
 
 Référence de Transact-SQL  
 
 
SET TRANSACTION ISOLATION LEVEL
Contrôle le comportement par défaut du verrouillage de transaction de toutes les instructions SELECT de Microsoft® SQL Server™ émises par une connexion.
 


 
[:petrus75]
et je suis une buse en bd, je fais vraiment ce que je peux  
 
 
gizmo : thks puor ton aide, je regarderais tout ca en detail lundi, thks alot

n°914282
gizmo
Posté le 03-12-2004 à 21:53:24  profilanswer
 

non, ils ne pompent pas l'un sur l'autre, ils essayent simplement de suivre la norme SQL :sarcastic:
PgSQL ne supporte actuellement que les transactions de niveau 1 et 3, soit read committed et serializable. Ce dernier conviendra a chrisbk pour autant qu'il n'ai pas a faire d'update dans sa transaction. Dans le cas contraire, il y a juste un risque qu'une des transactions saute et il suffit de la relancer. Ce mode n'est pas pris par défaut parce que c'est évidemment celui qui demande le plus de ressource.
 
Sinon, pour en revenir au problème des inserts sur table avec références. Une référence est une contrainte, et est donc traitée comme un trigger implicite. Par défaut, les contraintes sont déferred. Or, en cas d'insert concurrent dans la même table retrouve avec un lock qui est mis par les trigger qui attendent la fin de la transaction pour s'exécuter. Si on ajoutait des données via une autre transaction, et que ces données était committées, elles pourraient perturber le fonctionnement des trigger, par exemple si la référence se fait sur la même table.
Par contre, le fait que la table ne soit pas relachée si l'on spécifie que les contraintes sont immédiates est sans doute un bug.
 
Ah, oui, et encore une chose, arjuna, Dans oracle que tu sembles tant chérir, en cas d'insert, il fait un lock de type "row exclusive" qui est, j'ai vérifié, un lock sur toute la table, pas uniquement sur les lignes, exactement comme PgSQL.

n°914348
Arjuna
Aircraft Ident.: F-MBSD
Posté le 03-12-2004 à 22:58:15  profilanswer
 

chrisbk a écrit :

[:petrus75]
et je suis une buse en bd, je fais vraiment ce que je peux  


Si t'avais lu le post de gizmo, tu aurais vu que c'est la même instruction pour les deux SGBD (à moins que la remarque de skeye ayant motivé mon post ne m'étais pas destinée, c'est tout à fait possible, moi je l'avais pris comme ça ;))

n°914378
Arjuna
Aircraft Ident.: F-MBSD
Posté le 03-12-2004 à 23:32:57  profilanswer
 

gizmo > Ok pour le deffered. C'est une notion que je n'ai jamais maîtrisé, et que je met de côté régulièrement. Je ne pensais pas que son scope d'appliquait à toute la transaction. Si tu avais un lien vers une explication de ce fonctionnement, je t'en serais très reconnaissant. Pour moi, cela voulait simplement dire que si on insère une lot de X lignes (dans le cadre d'un "INSERT (SELECT ...)" par exemple), le SGBD insérait TOUTES les lignes, puis vérifiait les lignes une à une, avant de rollbacker tout le lot si une seule ligne est en erreur. Pour moi, ça restait cellé à l'intérieur de la transaction unitaire implicite à l'instruction. Après, peut-être que c'est le fait que PG ne supporte pas les transaction imbriquées qui fait que le LOCK s'étend à toute la transaction, je ne sais pas, c'est pour ça que je suis gourmand de plus de détails).
 
Sinon, pour ce qui est d'Oracle, j'ai bien tenté une fois ou deux de l'installer, mais j'ai jamais été foutu d'accéder à l'instance de la base crée. Niveau DBA, je suis nul. Par contre, tout comme les autres SGBD, la plupart des "SET ..." peuvent se faire de façon permanente via les outils de DBA.
 
Au taff, il m'arrive régulièrement de faire des batchs transactionnels d'import qui font des trucs du style :
 
"proutch, c'est moi que voilà, et j'ajoute dans la table de gestion des évènements 50 000 nouvelles lignes juste parceque le client machin il à commandé un truc mais qu'on n'avait pas en stock donc on a fait un mouvement de stock à partir d'un autre, et ça a généré une commande de réapprovionnement et on sait plus trop où on en est mais au final le nombre de lignes ajoutées/modifiées au sein de la même table est monstrueux".
 
Et pourtant, durant l'éxécution de ces batch, l'ERP qui gère cette base ne subit aucun ralentissement lié à d'éventuels LOCK, à moins évidement qu'on utilise des requêtes faisant appel aux lignes en cours d'insertion.
 
J'en déduis, sans connaître le paramétrage exact, que la base est configurée de façon à ne pas faire de table lock, et vu le type d'application, ce n'est certainement pas un mode d'isolation des transactions pouvant mettre en jeu la validité des données.
 
Deplus, via TOAD par exemple, il m'arrive très souvent de modifier/ajouter des données, et commiter uniquement plusieurs heures après, lorsque j'ai eu la confirmation de l'équipe comptable et de l'équipe de recouvrement par exemple que mes modifs sont ok (avec jeu de test dans la même session afin de bénéficier des modifs non commitées).
Encore une fois, je n'ai jamais entendu personne parmis les 3000 utilisateurs de l'ERP une seule plainte liée à un éventuel plantage à cause de ça.
 
Cela dit, en plus du paramètrage qui à mon avis est loin d'être celui par défaut, et celà va dans la logique exacte qui m'avait poussé à suggérer dans un autre topic l'utilisation minimale de FK et de trigger dans une base, toute la base de l'ERP ne contient pas une seule contrainte autre que des index uniques. D'après ton exeplication de l'insertion d'une table contenant des FK, c'est en effet aussi une explication possible du bon fonctionnement de la base que j'utilise par rapport à une base "standard".
 
Celà dit, avant de réalimenter la polémique du "faut-il faire tout gérer par l'applicatif, ou tout gérer par le SGBD", placer des FK et des triggers sur un tel type d'application serait impossible pour bon nombre de raisons indénombrable.
 
Un exemple pratique du dilemme d'un trigger à propos du contrôle des stocks :
- Je veux vendre un produit. J'ai pas assez de stock. Mais ce produit, je le vent pour dans 6 mois. Mais j'ai pas de réappro prévue dans ce délais. Cependant, le délais contractuel de réappro du fournisseur est de 2 mois. Alors je fais quoi ? Je jette la ligne ? Je la jette pas ? Bon, ok, je crée une ligne de commande d'achat. OK. Maintenant qu'elle est crée, je dois l'envoyer par fax. Merde, y'a pas de tonalité. Bon, j'attends 10 minutes, et je recommence (pendant ce temps, le gars au call center, il est en train de raconter ses vacances à Guernesey au client). Ah ! Ouf ! Le fax est parti ! Ha oui, mais ça veut pas dire que le fournisseur est en rupture de stock ! Alors... 3 heures après, le fournisseur qui a reçu le fax appelle le service des achats pour dire qu'il n'a plus de stock. Bon, déjà, là, le client a raccroché depuis 2 heures, il n'a pas aimé les vacances à Biarritz du centre d'appel. Mais bon, on imagine que la transaction tourne toujours, parcequ'elle est loin d'être terminée. Merde. Bon, le fournisseur peut pas livrer... Je fais quoi ? Ha, y'a un second fournisseur ! Ouais ! Merde, il a pas de fax. Ha, pis il n'a pas non plus de mail. Bon, on va demander à un acheteur de l'appeler. Putain, il est parti en vacances ce con ! Ah, y'en a un autre. Ouf ! OK, je peux être livré dans 4 mois, mais c'est plus le même prix d'achat. Faut faire valider par le service finance avant de signer la réappro. 3 heures après, après une réunion assez crispée, le trigger peut enfin repartir : c'est OK pour la réappro ! Euh... Le client ? Vous être toujours là ? Vous voulez un autre produit ? Ah ? Vous en voulez plus de celui-là ? Ah ben on n'en a pas assez prévu en réappro... Ah ? Vous êtes sur que vous n'en voulez pas plus finalement ? Bon, et le paquet cadeau, on se fait à quel nom ? Oui, c'est ça. Et vous payez comment ? Par chèque ? Oui, mais vous avez eu un dépassement le mois dernier. Vous n'avez plus le droit de commander par chèque jusqu'à notre prochaine réunion comptable à la fin du mois. Oui, je sais, c'est pour dans 6 mois... Mais moi je sais pas ce qui va être décidé pendant la réunion, pas plus qu'à la prochaine ou celle dans 6 mois ! Oui, c'est ça, vous restez en ligne jusqu'à la fin du mois. Quoique j'y pense... Repassez votre commande dans 6 mois, parceque la base, toutes les nuit on la reboote, alors la transaction elle sera annulée dans tous les cas vous comprennez ? Que je vous prends pour un con ? Mais non monsieur ! C'est juste que je suis un trigger qui bosse dans un SGBD-R, donc les relations c'est moi qui doit m'en charger... Le relations clients ? Comment ça ? Oui, certainement que je ne suis pas doué en relation client, mais vous comprenez, c'est pas mon job. [:spamafote]
 
Bref, un peu édulcoré, avec pas mal de point de toute façon impossible à traîter au sein d'une même transaction (ou alors tout le monde viens mettre à jour l'était des évènements liés à la commande sur le même PC pour utiliser la même transaction). Cela démontre tout de même bien que le problème le plus basic est absolument ingérable pas trigger, et que dans le domaine de l'ERP, seul le logiciel est à même de résoudre des problèmes aussi complexes, et ce, en comptant sur les décisions des humains qui l'utilisent.
 
Après tout, dans 6 mois, le dépassement bancaire du client sera de toute façon résorbé, on a un historique de ses achats lors de la prise de commande et un joli warning s'il est en dépassement, on lui interdira de commander plus d'ici là, voilà tout. Quand à une réappro de 6 mois, on n'a jamais vu ça, le produit n'est pas en fin de vie, le batch de réappro va préparer une commande d'approvisionnement consolidée avec toutes les demandes du jours dès ce soir, l'affaire sera classée !
 
Bref, FK et trigger, c'est pas adapté pour les applis sur lesquelles je bosse, donc il est vrai que je suis extrêment rarement confronté à ce genre de problème.
 
Celà dit je reste toujours preneur d'une petit explication plus détaillée du fonctionnement "deffered". :)

n°914384
gizmo
Posté le 03-12-2004 à 23:37:06  profilanswer
 

'tain mais faut faire des patés moins long ou alors les couper en petit, pas le courage de lire tout ça en une fois moi :sweat:

n°914390
Arjuna
Aircraft Ident.: F-MBSD
Posté le 03-12-2004 à 23:42:16  profilanswer
 

Boarf, y'en a un gros tiers, c'est un délire qui j'espère te fera au moins rire (en tout cas, je me suis bien marré en l'écrivant :p)

n°914395
Arjuna
Aircraft Ident.: F-MBSD
Posté le 03-12-2004 à 23:51:51  profilanswer
 

Sinon, pour ce qui est de ma remarque "qui à copier sur qui", c'était surtout que pas expérience, chaque éditeur revois la norme SQL à sa sauce, et notamment c'est un point qu'on reproche à M$ pour la plupart de ses produits, et SQL Server n'y échappe pas, alors j'étais quelque peu stuppéfait que ce soit rigoureusment les mêmes syntaxes entre PG et MSSQL, d'autant plus que si mes souvenir sont bons, PG est un des SGBD qui respecte le plus la norme.
 
Celà dit, je ne savais même pas que les "SET ..." étaient détaillés dans la norme. Et vu que malgré la jeunesse du moteur de SQL Server, ce dernier me semble plus complète que celui de PG (par exemple, il supporte les transactions imbriquées depuis au moins la version 7.0), j'en déduis qu'un certain nombre de ses instructions reconnues par PG sont implémentées sur MSSQL depuis plus longtemps. Mais si c'est dans la norme, je comprends mieu pourquoi PG aurait repris la même syntaxe ;)

n°914397
chrisbk
-
Posté le 03-12-2004 à 23:53:50  profilanswer
 

sql serait il aussi une norme fleuve pour que tout le monde en chie a l'implanter ? d'ou vient cette boulimie de 'feature' et a quoi ca sert si c'st tjs a moitié implanté ?

n°914404
el muchach​o
Comfortably Numb
Posté le 04-12-2004 à 00:02:19  profilanswer
 

chrisbk a écrit :

sql serait il aussi une norme fleuve pour que tout le monde en chie a l'implanter ? d'ou vient cette boulimie de 'feature' et a quoi ca sert si c'st tjs a moitié implanté ?


Dans le livre "Anti patterns", j'ai lu que SQL a été pondu par un groupement de sociétés qui se sont regroupées en comité et ont voulu mettre tout ce qu'elles pouvaient dedans. C'est donné dans le bouquin comme l'exemple type de ce qu'il ne faut pas faire en comité.
 
Sinon la version 8 de Postgres est dispo en version beta 5 sur http://www.postgresqlfr.org/. En attendant la version 8 finale, p-ê que vous pouvez continuer vos dev avec cette version.
 
Arjuna > Le moteur de MS SQL n'a rien de jeune. C'est un dérivé de Sybase.


Message édité par el muchacho le 04-12-2004 à 00:13:37
n°914409
gizmo
Posté le 04-12-2004 à 00:06:10  profilanswer
 

chrisbk a écrit :

sql serait il aussi une norme fleuve pour que tout le monde en chie a l'implanter ? d'ou vient cette boulimie de 'feature' et a quoi ca sert si c'st tjs a moitié implanté ?


C'est pas vraiment une boulimie, c'est plutôt le fait qu'il s'agisse, comme pour le html, d'une norme crée sur le tare. Ca provient d'un DBMS (me rappelle plus lequel) qui a eu un certains succès, du coup, on a voulu faire la même chose ailleurs, et donc on s'est mis ensemble pour mettre des base communes > SQL92 puis on s'est rendu compte qu'il manquait des choses et que certains (bouh les vilains!) prennaient de l'avance tout en se laissant certaines libertées sur la norme. On rectifie le tire > SQL99. Et puis comme c'est toujours pas suffisant, on continue avec SQL200x.
 
Tu rajoute à cela le fait que pour chacune des normes ils ont définis des niveaux d'implémentation et tu as une idée du bordel qui fait que tout le monde essaye de suivre et la norme, et Oracle, parce que bon, ca a beau être un veau, c'est le leader.

n°914417
Arjuna
Aircraft Ident.: F-MBSD
Posté le 04-12-2004 à 00:20:43  profilanswer
 

Ben à la base, la plupart des entorses à la normes sont dûes à des choix d'implémentation des fonctions qui sont incompatibles avec la structure imposée par la norme.
Par exemple, les types auto-incréments. Je ne sais pas trop ce que préconnise la norme. En tout cas, trois solutions ont été adoptées à ma connaissance :
- Oracle : Un bête objet "sequence" permet de générer un "nextval" ou de rappeler le "currval". Lors d'un insert, on va donc interroger la séquence correspondant au champ particulier de la table, et on récupère une valeurs obligatoirement unique. Ca à trois avantages et deux inconvénients :
a1) On peut mettre n'importe quel valeur dans le champ correspondant au numauto, simplement parceque la séquence n'est pas liée physiquement à la table. On fait généralement un trigger, mais c'est pas obligatoire.
a2) On peut utiliser différentes séquences pour générer des compteurs différents dans un même champ, dans le cadre d'une double clé par exemple. Si j'ai une table "commande", selon si le champs TYPE est "achat" ou "vente", je pourrai prendre la séquence dédiée à l'une des deux fonctions pour récupérer un numéro. De la même façon, on peut plus aisément gréer des ID calculé, du style "2004120001" pour un numéro de commande. Il suffit de réinitialiser la valeur de départ de la séquence à chaque début de mois.
a3) On peut avoir plusieurs champ numéro auto dans une même table (je n'ai pas d'exemple d'utilité, mais je suis sûr que ça doit arriver)
 
i1) La séquence ne vérifie pas que le prochain numéro n'existe pas dans la table. Il faut donc faire un check manuel au moment de l'insert pour être sûr qu'une ligne ajoutée "à la main" n'utilise pas déjà le numéro.
i2) Le nextval n'est pas rollbackage, et pour la raison i1, ne va pas rechercher les id des lignes supprimées. On génère donc des trous.
 
- La solution "à la MSSQL". On a un type qui crée une nouvelle valeur non déjà existance à chaque nouvelle ligne. Ca a deux avantages, et 4 inconvénients :
a1 et 2) Le compteur est lié à la table. Par conséquent, il est obligatoirement généré, et ne peut pas prendre une valeur existance, même si une ligne a été rentrée à la main.
 
i1) Malgré la liaison entre le compteur et la table, le numéro auto est incapable de boucher les trous
i2) De par son mode de fonctionnement, on ne peut pas définir son format, c'est un compteur bête et méchant (avec des alter, on peut bidouiller un peu, mais ça reste de la bidouille). C'est donc bien moins souple que l'utilisation de séquences multiples pour un même champ.
i3) Il me semble qu'on ne peut avoir ce type de champ qu'une seule fois pas table
i4) Si on ne veut pas du chiffre automatique, il faut le désactiver à la main avant l'insertion d'une ligne, et le réactiver ensuite. Deplus, si le compteur est à 5 et qu'on ajoute la ligne "10", alors il continue à "11"
i5) Ce numéro n'est pas rollbackable. Donc si l'insertion d'une ligne échoue, son ID ne sera pas regénéré.
 
- La méthode "à la MySQL"
Là, c'est presque comme le système MSSQL, avec moins d'inconvénients, et quelques avantages de la solution d'Oracle
a1) On peut avoir plusieur numéro auto dans une même table
a2) Quelque soit la situation, les trous sont bouchés
a3) On peut forcer une valeur sans devoir le spécifier explicitement dans une pré-requête.
a4) Si deux compteurs sont présents dans une même table, et participent tous deux à la PK, alors ils vont se remplir "intelligement" de façon à 1-1 1-2 2-1 2-2 ...
 
i1) On ne peut pas alimenter les compteurs de plusieurs sources. Ce sont de bêtes compteur "1, 2, 3", on n'a donc pas la souplesse des séquences.
i2) A vérifier, mais je pense que pour la raison i1, le format du compteur n'est pas définissable.
 
Bref, ce petit exemple qui indique pourquoi tout le monde ne fait pas pareil. Chaque solution a ses avantages et ses inconvénients. Parmis toutes ces solutions, une seule est préconisée par la norme (et peut-être qu'elle ne fait même pas partie de ces trois là).
C'est pareil pour la plupart des autres éléments.
 
A noter aussi que pendant un long moment, certains SGBD (Oracle par exemple) évoluaient beaucoup plus vite que la norme, et ont subit la même chose que Microsoft et Netscape avec IE, Navigator et le HTML : à force d'être en avance sur le W3C, ils se sont pris une claque parceque la norme n'a retenu qu'une faible partie de leurs propositions, et ça a sonné le gla de Navigator, tandis que le moteur de IE se traîne des gamelles qui en rendent la compatibilité très hasardeuse aujourd'hui.

n°914418
Arjuna
Aircraft Ident.: F-MBSD
Posté le 04-12-2004 à 00:22:05  profilanswer
 

el muchacho a écrit :


Arjuna > Le moteur de MS SQL n'a rien de jeune. C'est un dérivé de Sybase.


Je t'assûre que par rapport à Oracle ou DB2 par exemple, il est TRES jeune (ou pas mature si tu préfère ;)), même si le gouffre a tendance à se combler assez rapidement.

n°914419
Arjuna
Aircraft Ident.: F-MBSD
Posté le 04-12-2004 à 00:24:16  profilanswer
 

désolé gizmo, j'ai encore fait un gros paté :D
 
faut que je me reconvertisse en pipotteur au bureau marketing de je ne sais quelle boîte, ça m'a l'air innhé chez moi :D (faudra juste que j'apprenne à écrire sans faute pour ça)
 
 

gizmo a écrit :

C'est pas vraiment une boulimie, c'est plutôt le fait qu'il s'agisse, comme pour le html, d'une norme crée sur le tare. Ca provient d'un DBMS (me rappelle plus lequel) qui a eu un certains succès


C'était pas le père direct d'Ingres ?
 
En tout cas, je me souviens avoir discuté du sujet avec un gars "de l'époque :D", et il m'avait confié un truc très marrant.
 
La norme SQL92 provient de ce que le soft savait faire "en théorie", parceque par exemple, un truc bête :
 
SELECT T1.VAL FROM T1 INNER JOIN T2 ON T1.ID = T2.ID WHERE T2.VAL = 1
 
Ca marchait.
Maintenant, tu refaisait la même requête avec deux champs pour la jointure, et il fallait écrire la clause "inner join" deux fois, sous peine d'avoir un plantage du server :D
Chose qui a été corrigée que deux versions plus tard, alors que les premiers SGBD dérivés du SQL92 supportaient la chose très bien :D


Message édité par Arjuna le 04-12-2004 à 00:28:51
n°914741
Moktar1er
No one replies...
Posté le 04-12-2004 à 15:39:11  profilanswer
 

un version beta sur 1 serveur de prod? nan je ne crois pas [:itm]
sinon merci pour les conseils gizmo, on verra ça avec chris lundi
de toutes façons, faut préciser que la table ne contient que des données TEMPORAIRES, données qui n'auront plus lieu d'être à la fin du traitement complet
l'intégrité sera a priori assurée quand même du fait qu'un select de bon aloi sert déjà à remplir cette table donc...
sinon j'avais une question, quand je commence une session (BEGIN), le COMMIT n'est-il pas pris en compte comme commande de fin de session?

n°914880
gizmo
Posté le 04-12-2004 à 19:51:37  profilanswer
 

moktar1er a écrit :


sinon j'avais une question, quand je commence une session (BEGIN), le COMMIT n'est-il pas pris en compte comme commande de fin de session?


Tu veux dire transaction? dans ce cas, oui, le commit est bien synonyme de end;

n°914881
gizmo
Posté le 04-12-2004 à 19:52:06  profilanswer
 

bon, lecture des patés, j'ai pris deux aspirines de manière préventive :D

n°914882
Moktar1er
No one replies...
Posté le 04-12-2004 à 19:53:19  profilanswer
 

gizmo a écrit :

Tu veux dire transaction? dans ce cas, oui, le commit est bien synonyme de end;


m'en doutais, mais j'ai eu un doute en voyant son exemple là:
http://forum.hardware.fr/forum2.ph [...] t=#t913954
 
merci :jap:

n°914907
gizmo
Posté le 04-12-2004 à 20:59:26  profilanswer
 

ayé, j'ai lu.
 
Bon, dans l'ordre, si j'ai bien noté:
 
- le deferred, c'est pas sorcier, ca se met à la fin de la transaction pour une raison purement pratique. Exemple: Dans l'ancien modèle de notre outil, le schéma contenait son modèle en son sein, ce qui fait qu'il se lisait lui-même pour savoir s'il pouvait insérer un objet d'un certain type. Problème: comment insérer le schéma au départ vu qu'il n'avait pas de schéma pour valider que les objets schémas étaient valides (je sais, on est un peu tordu). La solution se situe au niveau des transactions et des contraintes defferred. Ainsi, on pouvait introduire au sein d'une transaction les objets du schéma dans les différentes tables et les validations ne se faisaient qu'en fin de transaction... grâce aux objets fraichement installés :D (Bon, après on a virer ce système mais c'est pour l'exemple)
 
Et pour des raisons de performance, un DBMS n'implémentear jamais un système de contrôle de contrainte qui travaille au niveau ligne au cours d'une insertion/modification multiple, c'est nettement plus simple de faire des traitement par lot.
 
- Il y a une différence au niveau des lock lorsque l'on parle d'insert et d'update. Un update, que ce soit dans PG ou dans Oracle travaille ses lock au niveau ligne, par contre, les insert se font toujours avec un lock au niveau table.  
En théorie, on peut effectivement mettre le LOCK que l'on désire ou le niveau que l'on veut à une transaction/session. Mais en pratique, si le DBMS a besoin de plus, soit il jettera la requète, soit il mettra la priorité du lock à la hausse le temps nécessaire.
Cependant, le coup du lock qui perdure sur une table avec contrainte malgré le mode IMMEDIATE, je vais me renseigner parce que je ne vois pas ce qui empècherait de lever le lock après l'insertion.
 
- MySQL ne gère pas les trous dans son auto_increment. Si tu jette le dernier id, soit par un delete, soit par un rollback, il passera au suivant lors du prochain insert.
En passant, Pg utilise un système encore légèrement différent que les trois précédents (pour information): il y a les SEQUENCE, identiques à celles d'oracle, ou pioche qui veut quand il en a envie, avec un pas incrémental au choix et une remise à niveau si nécessaire, et il y a egalement le type de colonne SERIAL qui est une colonne qui génère automatiquement une SEQUENCE et qui a comme valeur par défaut le nextval de cette séquence.
 
Voila, je pense que j'ai rien oublié. Ah, si, j'ai pas bien compris l'histoire des 6 mois de médocs, mais, à mon avis, les limitations que tu vois sur les FK et triggers viennent plutôt de la manière dont les tables mélangent les objets dans le modèle de ton ERP qu'autre chose (cf tes posts précédents sur les modèles à x colonnes etc)

n°915740
Arjuna
Aircraft Ident.: F-MBSD
Posté le 06-12-2004 à 14:18:56  profilanswer
 

OK. Bien compris pour le deferred (même si je suis pas convaincu que c'est la façon dont ça devrait marcher :D)
 
Sinon, pour MySQL, ça dépends peut-être des versions, parceque sûr et certain, sur le site que j'avais commencé à écrire sur mon compte multi-mania (et que j'avais auparavant codé en local sur une machine sous Linux), MySQL bouchait bel et bien les trous. Dans mon cas, ce n'était pas dérangeant, mais ça peut le devenir dans certains cas, où on décide d'utiliser l'ID comme facteur d'ordre chronologique.
 
Sinon, c'est mon explication du trigger/fk que t'as pas compris ?
Non, à la base, le fait de tout mélanger le gène rien. Faut prendre le problème d'un point de vue purement "logique", sans ce soucier du fonctionnement du SGBD.
 
Je reprends ;)
 
Imagine. Tu as un système qui gère des produits à la vente.
Tu as des stocks. L'outils gère une procédure de réapprovisionnement automatique lorsque les stocks ne sont pas suffisants.
 
Une client désire commander 500 unité d'un produit pour le 1/05/2005.
 
Actuellement, dans les stocks, il y a 800 unités.
300 unités de plus sont en attente de livraison avant le 01/05/2005. Ca fait dont 1100 unités disponibles pour le 01/05/2005.
Cependant, d'ici le 1/05/2005, 1000 de ces 1100 unités sont déjà réservées pour d'autres commandes. Il ne reste donc que 100 unités, donc ce n'est pas suffisant.
 
Un trigger "simple" va déjà pédaler un moment dans la choucroute pour gérer tout ça, et bloquer le client, parcequ'il a trouvé qu'il n'y avait pas assez de produits en stock pour le 1/05/2005.
 
Cependant, le 01/05/2005, c'est quand même dans 6 mois. D'ici là, à priori, on va avoir de se faire réapprovisionner.
 
Bon. On regarde donc dans la table des fournisseurs, ceux qui peuvent réapprovisionner ce produit. Son délais contractuel (il s'y est engagé contracutllement) pour ce produit est de 100 jours. OK. Ca devrait aller.
 
Seulement, ça ne garantis rien. Si le fournisseur ne peux pas répondre, il lui suffit de refuser la commande.
 
On doit donc lui envoyer la commande d'achat. Si cette dernière peut être générée de façon 100% automatique, la réponse aura du mal à l'être, et encore moins dans un délais acceptable pour que ce soit le trigger qui s'en occupe.
De la même façon, si on bosse comme ça avec un trigger, on bosse forcément en flux tendu.
 
Essaie de passer 30 commandes d'un même produit, par 3 ou 4 unités à un même fournisseur dans la même journée, et tu vas voir ce qu'il va te dire (et tu vas voir ce qu'à ton dépôt ils vont te dire quand ils votn devoir déballer 30 cartons "pour rien" ).
Bref, il faut consolider les commandes d'achat, ce qu'un trigger sera incapable de faire, puisqu'il a absolument d'une réponse "là maintenant tout de suite" pour savoir s'il doit laisser passer la ligne ou non.
 
Bref, tout ça, ça n'a rien à voir avec le modèle des données en lui-même, mais l'orientation métier de l'application. Dans tous les cas, le système ne pourra qu'au mieu lever un warning ou afficher une info, afin d'aider à la décision de l'humain qui s'en sert.
 
Ainsi, afin d'éviter des traîtements inutiles dans 99% des cas, et pour arriver de toute façon au même résultat, il faut décharger la base des contraintes, et faire les checks dans la base.
 
Pour les FK, je suis d'accord, c'est moins vrai. Celà dit, à nouveau, dans le monde de l'ERP, les FK sont rarement "simples".
 
Mettons une réclamation. Elle va être liée par exmeple à une commande, à une livraison, ou un produit.
Si la commande peut être déduite de la livraison, l'inverse n'est pas vrai. Quant au produit, il est totalement séparé. Ainsi, il va falloir faire un trigger relativement complexe pour pouvoir checker cette FK conditionnelle.
 
De plus, que va faire la FK ? Vérifier qu'on n'a pas saisi un produit qui n'existe pas ? Ben oui, mais non, ça va pas. Parceque déjà, le produit provient d'une liste, donc je ne pourrai pas en saisir un qui n'existe pas. Ce contrôle sera donc inutile. Par contre, on ne peut faire une claim que sur un produit étant en catalogue. Hors la table contient des produits qui ne sont pas en catalogue. La FK sera donc insuffisante. Idem, on ne peux pas faire une claim sur une commande qui n'a pas été validée ni facturée (ça va de soit). Une simple FK encore une fois ne saura en aucun cas valider ces infos.

mood
Publicité
Posté le   profilanswer
 

 Page :   1  2  3
Page Suivante

Aller à :
Ajouter une réponse
 

Sujets relatifs
petite aide SQL requete imbriqué[Résolu] Exploiter 2 fois un résultat d'une requête
problème de syntaxe avec une requête SQLrequete croisée ??
Requete formulaire dans access[JSP/SERVLET] Sauvegarder une requête pour l'exécuter apres login...
Requete sql sur plusieurs tables avec nom de la tableAider moi pour une requete
Requête spéciale[MYSQL] Requete multi base de données
Plus de sujets relatifs à : aidez une pauvre etudiante avec une requete bloquante


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR