web-dev-qa-db-fra.com

Supprimer des lignes de plusieurs tables à l'aide d'une seule requête (SQL Express 2005) avec une condition WHERE

C'est la requête que j'utilise:

 DELETE TB1.*, TB2.*
   FROM TB1
        INNER JOIN TB2 ON TB1.PersonID = TB2.PersonID 
  WHERE (TB1.PersonID)='2'

Cela fonctionne très bien dans MS Access mais génère une erreur (syntaxe incorrecte près de ','.) Dans SQL Server Express 2005. 

Comment le résoudre? S'il vous plaît aider.

18
Jobi

Vous ne pouvez pas utiliser DELETE à partir de plusieurs tables avec une seule expression dans SQL 2005 - ou de tout autre code SQL standard à cet égard. Access est l'exception ici.

La meilleure méthode pour obtenir cet effet consiste à spécifier FOREIGN KEYS entre les tables avec un ONDELETEtrigger

18
Matijs

Pourquoi n'utilisez-vous pas un DELETE CASCADE FK?

11
Cesar

Cela ne peut pas être fait en une seule déclaration. Vous devrez utiliser 2 déclarations

DELETE FROM TB1 WHERE PersonID = '2';
DELETE FROM TB2 WHERE PersonID = '2';
3
Adriaan Stander

Comme je le sais, vous ne pouvez pas le faire en une phrase.

Mais vous pouvez créer une procédure stockée qui supprime les modifications souhaitées dans n'importe quelle table d'une transaction, ce qui est presque identique.

2
j.a.estevan

Spécifiez la clé étrangère pour les tables de détails faisant référence à la clé primaire du maître et définissez la règle de suppression = Cascade.

Désormais, lorsque vous supprimez un enregistrement de la table principale, tous les autres enregistrements de la table de détails basés sur la valeur de la clé primaire de suppression de lignes sont automatiquement supprimés.

Ainsi, dans ce cas, une requête de suppression unique de la table principale peut supprimer des données de tables principales ainsi que des données de tables enfants.

1
Himadri

Je ne pense pas que vous puissiez supprimer plusieurs tables à la fois (même si je ne suis pas certain).

Il me semble cependant que vous feriez mieux de réaliser cet effet avec une relation qui supprime les cascades. Si vous faites cela, vous pourrez supprimer l'enregistrement d'une table et les enregistrements de l'autre seront automatiquement supprimés.

Par exemple, supposons que les deux tables représentent un client et ses commandes. Si vous configurez la relation avec les suppressions en cascade, vous pouvez simplement supprimer un enregistrement dans la table des clients et les commandes seront automatiquement supprimées.

Voir la documentation MSDN sur en cascade des contraintes d'intégrité référentielle .

1
Alex Deem

Vous pouvez utiliser quelque chose comme ce qui suit:

DECLARE db_cursor CURSOR FOR  
SELECT name 
FROM master.dbo.sysdatabases 
WHERE name IN ("TB2","TB1")  -- use these databases

OPEN db_cursor   
FETCH NEXT FROM db_cursor INTO @name   


WHILE @@FETCH_STATUS = 0   
BEGIN   

       DELETE FROM @name WHERE PersonID ='2'

       FETCH NEXT FROM db_cursor INTO @name   
END  
0
Yablargo

J'utilise ceci pour nettoyer des données dans des bases de données de test/développement. Vous pouvez filtrer par nom de table et nombre d'enregistrements. 

DECLARE @sqlCommand VARCHAR(3000);
DECLARE @tableList TABLE(Value NVARCHAR(128));
DECLARE @TableName VARCHAR(128);
DECLARE @RecordCount INT;

-- get a cursor with a list of table names and their record counts
DECLARE MyCursor CURSOR FAST_FORWARD
FOR SELECT t.name TableName,
           i.rows Records
    FROM sysobjects t,
         sysindexes i
    WHERE 
          t.xtype = 'U'              -- only User tables
          AND i.id = t.id          
          AND i.indid IN(0, 1)       -- 0=Heap, 1=Clustered Index
          AND i.rows < 10            -- Filter by number of records in the table
          AND t.name LIKE 'Test_%';  -- Filter tables by name. You could also provide a list:
                                     -- AND t.name IN ('MyTable1', 'MyTable2', 'MyTable3');
                                     -- or a list of tables to exclude:
                                     -- AND t.name NOT IN ('MySpecialTable', ... );

OPEN MyCursor;

FETCH NEXT FROM MyCursor INTO @TableName, @RecordCount;

-- for each table name in the cursor, delete all records from that table:
WHILE @@FETCH_STATUS = 0
    BEGIN
        SET @sqlCommand = 'DELETE FROM ' + @TableName;
        EXEC (@sqlCommand);
        FETCH NEXT FROM MyCursor INTO @TableName, @RecordCount;
    END;

CLOSE MyCursor;
DEALLOCATE MyCursor;

Informations de référence:

0
Marathon55

vous pouvez rejoindre comme ça

DELETE t2
   FROM TB1 t1
        INNER JOIN TB2 t2 ON t1.PersonID = t2.PersonID 
  WHERE t1.PersonID = '2'

mais comme Alex l'a mentionné, un seul à la fois.

Vous avez besoin d'une contrainte de cascade sur la table pour tout faire en même temps

0
Justin
CREATE PROCEDURE sp_deleteUserDetails
    @Email varchar(255)
AS
    declare @tempRegId as int
    Delete UserRegistration where Email=@Email  
    set @tempRegId = (select Id from UserRegistration where Email = @Email)
    Delete UserProfile where RegID=@tempRegId

RETURN 0
0
Hari Kumar