Usuń wszystkie tabele, których nazwy zaczynają się od określonego ciągu

150

Jak mogę usunąć wszystkie tabele, których nazwy zaczynają się od podanego ciągu?

Myślę, że można to zrobić za pomocą dynamicznego SQL i INFORMATION_SCHEMAtabel.

Blorgbeard wyszedł
źródło

Odpowiedzi:

151

Może być konieczne zmodyfikowanie zapytania, aby uwzględnić właściciela, jeśli w bazie danych jest więcej niż jeden.

DECLARE @cmd varchar(4000)
DECLARE cmds CURSOR FOR
SELECT 'drop table [' + Table_Name + ']'
FROM INFORMATION_SCHEMA.TABLES
WHERE Table_Name LIKE 'prefix%'

OPEN cmds
WHILE 1 = 1
BEGIN
    FETCH cmds INTO @cmd
    IF @@fetch_status != 0 BREAK
    EXEC(@cmd)
END
CLOSE cmds;
DEALLOCATE cmds

Jest to czystsze niż stosowanie dwuetapowego podejścia polegającego na wygenerowaniu skryptu i uruchomieniu. Ale jedną z zalet generowania skryptów jest to, że daje możliwość przejrzenia całości tego, co ma zostać uruchomione, zanim faktycznie zostanie uruchomione.

Wiem, że gdybym miał to zrobić z produkcyjną bazą danych, byłbym tak ostrożny, jak to tylko możliwe.

Naprawiono próbkę edycji kodu.

Curt Hagenlocher
źródło
5
Może być konieczne kilkakrotne uruchomienie tego skryptu z powodu ograniczeń klucza obcego między tabelą główną a tabelą szczegółów.
Alexander Prokofyev,
7
W SQL Server 2005 musiałem zmienić ostatnie dwie linie na close cmds; deallocate cmds.
Hamish Grubijan
Ostrzeżenie : to rozwiązanie może również usunąć tabele utworzone przez SQL Server! Poniższe rozwiązanie pozwala uniknąć tego i usuwa tabele w kolejności zależności klucza obcego.
Tony O'Hagan,
To nie zadziałało dla mnie. Odpowiedź na to pytanie zadziałała: stackoverflow.com/questions/5116296/…
Ayushmati
115
SELECT 'DROP TABLE "' + TABLE_NAME + '"' 
FROM INFORMATION_SCHEMA.TABLES 
WHERE TABLE_NAME LIKE '[prefix]%'

Spowoduje to wygenerowanie skryptu.

Dodanie klauzuli sprawdzającej istnienie tabeli przed usunięciem:

SELECT 'IF OBJECT_ID(''' +TABLE_NAME + ''') IS NOT NULL BEGIN DROP TABLE [' + TABLE_NAME + '] END;' 
FROM INFORMATION_SCHEMA.TABLES 
WHERE TABLE_NAME LIKE '[prefix]%'
Xenph Yan
źródło
10
Mogę dodać, aby usunąć nawiasy, zastępując „przedrostek” przedrostkiem docelowym.
Levitikon
10
MYSQL: SELECT concat ('DROP TABLE', TABLE_NAME, ";") jako dane FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME LIKE '[prefiks]%' --- dla tych, którzy lubią mnie, znaleźli ten wątek
Andre
1
Wynik zawiera również wyświetlenia
Ondra
1
Nie zapomnij o ucieczce _, jeśli jest to część Twojego prefiksu, np. WHERE TABLE_NAME LIKE 'em\_%' ESCAPE '\';
EM0
3
To generuje skrypt, ale jak można go wykonać?
daOnlyBG
16

Pozwoli to uzyskać tabele w kolejności klucza obcego i uniknąć porzucenia niektórych tabel utworzonych przez SQL Server. t.OrdinalWartość będzie kroić tabele na warstwy zależności.

WITH TablesCTE(SchemaName, TableName, TableID, Ordinal) AS
(
    SELECT OBJECT_SCHEMA_NAME(so.object_id) AS SchemaName,
        OBJECT_NAME(so.object_id) AS TableName,
        so.object_id AS TableID,
        0 AS Ordinal
    FROM sys.objects AS so
    WHERE so.type = 'U'
        AND so.is_ms_Shipped = 0
        AND OBJECT_NAME(so.object_id)
        LIKE 'MyPrefix%'

    UNION ALL
    SELECT OBJECT_SCHEMA_NAME(so.object_id) AS SchemaName,
        OBJECT_NAME(so.object_id) AS TableName,
        so.object_id AS TableID,
        tt.Ordinal + 1 AS Ordinal
    FROM sys.objects AS so
        INNER JOIN sys.foreign_keys AS f
            ON f.parent_object_id = so.object_id
                AND f.parent_object_id != f.referenced_object_id
        INNER JOIN TablesCTE AS tt
            ON f.referenced_object_id = tt.TableID
    WHERE so.type = 'U'
        AND so.is_ms_Shipped = 0
        AND OBJECT_NAME(so.object_id)
        LIKE 'MyPrefix%'
)
SELECT DISTINCT t.Ordinal, t.SchemaName, t.TableName, t.TableID
FROM TablesCTE AS t
    INNER JOIN
    (
        SELECT
            itt.SchemaName AS SchemaName,
            itt.TableName AS TableName,
            itt.TableID AS TableID,
            Max(itt.Ordinal) AS Ordinal
        FROM TablesCTE AS itt
        GROUP BY itt.SchemaName, itt.TableName, itt.TableID
    ) AS tt
        ON t.TableID = tt.TableID
            AND t.Ordinal = tt.Ordinal
ORDER BY t.Ordinal DESC, t.TableName ASC
Tony O'Hagan
źródło
3
Szybka poprawka: nazwa TableName pojawia się kilka razy w klauzulach WHERE i powinna zostać zastąpiona przez OBJECT_NAME (czyli identyfikator obiektu). Niezły scenariusz!
dowcipny
6

W Oracle XE to działa:

SELECT 'DROP TABLE "' || TABLE_NAME || '";'
FROM USER_TABLES
WHERE TABLE_NAME LIKE 'YOURTABLEPREFIX%'

Lub jeśli chcesz usunąć ograniczenia i zwolnić miejsce , użyj tego:

SELECT 'DROP TABLE "' || TABLE_NAME || '" cascade constraints PURGE;'
FROM USER_TABLES
WHERE TABLE_NAME LIKE 'YOURTABLEPREFIX%'

Co wygeneruje zestaw DROP TABLE cascade constraints PURGEinstrukcji ...

W VIEWStym celu:

SELECT 'DROP VIEW "' || VIEW_NAME || '";'
FROM USER_VIEWS
WHERE VIEW_NAME LIKE 'YOURVIEWPREFIX%'
Rosdi Kasim
źródło
Działał doskonale. Miał 61 037 pustych tabel do usunięcia z bazy danych używanej do kontroli jakości. Użyłem przykładu ograniczeń kaskadowych. Wygenerowano dane wyjściowe, a następnie skopiowano je wszystkie do skryptu i uruchomiono. Trwało to wieczność, ale działało jak urok! Dzięki!
tehbeardedone
5

Widziałem ten post, gdy szukałem instrukcji mysql, aby usunąć wszystkie tabele WordPress oparte na @Xenph Yan, oto co ostatecznie zrobiłem:

SELECT CONCAT(  'DROP TABLE `', TABLE_NAME,  '`;' ) AS query
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE  'wp_%'

to da ci zestaw zapytań upuszczających dla wszystkich tabel zaczynających się od wp_

talsibony
źródło
5

Oto moje rozwiązanie:

SELECT CONCAT('DROP TABLE `', TABLE_NAME,'`;') 
FROM INFORMATION_SCHEMA.TABLES 
WHERE TABLE_NAME LIKE 'TABLE_PREFIX_GOES_HERE%';

I oczywiście musisz zastąpić TABLE_PREFIX_GOES_HEREprzedrostkiem.

venedor
źródło
5
EXEC sp_MSforeachtable 'if PARSENAME("?",1) like ''%CertainString%'' DROP TABLE ?'

Edytować:

sp_MSforeachtable jest nieudokumentowane, dlatego nie nadaje się do produkcji, ponieważ jego zachowanie może się różnić w zależności od wersji MS_SQL.

mrosiak
źródło
Niesamowita jedna linijka! To powinno być głosowane na szczycie.
user3413723
4
CREATE PROCEDURE usp_GenerateDROP
    @Pattern AS varchar(255)
    ,@PrintQuery AS bit
    ,@ExecQuery AS bit
AS
BEGIN
    DECLARE @sql AS varchar(max)

    SELECT @sql = COALESCE(@sql, '') + 'DROP TABLE [' + TABLE_NAME + ']' + CHAR(13) + CHAR(10)
    FROM INFORMATION_SCHEMA.TABLES
    WHERE TABLE_NAME LIKE @Pattern

    IF @PrintQuery = 1 PRINT @sql
    IF @ExecQuery = 1 EXEC (@sql)
END
Cade Roux
źródło
2

Odpowiedź Xenpha Yana była znacznie czystsza niż moja, ale tutaj jest moja.

DECLARE @startStr AS Varchar (20)
SET @startStr = 'tableName'

DECLARE @startStrLen AS int
SELECT @startStrLen = LEN(@startStr)

SELECT 'DROP TABLE ' + name FROM sysobjects
WHERE type = 'U' AND LEFT(name, @startStrLen) = @startStr

Po prostu zmień tableNamena znaki, które chcesz wyszukiwać.

FryHard
źródło
1

To zadziałało dla mnie.

DECLARE @sql NVARCHAR(MAX) = N'';

SELECT @sql += '
DROP TABLE ' 
    + QUOTENAME(s.name)
    + '.' + QUOTENAME(t.name) + ';'
    FROM sys.tables AS t
    INNER JOIN sys.schemas AS s
    ON t.[schema_id] = s.[schema_id] 
    WHERE t.name LIKE 'something%';

PRINT @sql;
-- EXEC sp_executesql @sql;
POPIÓŁ
źródło
0
select 'DROP TABLE ' + name from sysobjects
where type = 'U' and sysobjects.name like '%test%'

- Test to nazwa tabeli

Shashank
źródło
to w rzeczywistości niczego nie wykonuje, po prostu zwraca zestaw poleceń.
Stealth Rabbi
0
SELECT 'if object_id(''' + TABLE_NAME + ''') is not null begin drop table "' + TABLE_NAME + '" end;' 
FROM INFORMATION_SCHEMA.TABLES 
WHERE TABLE_NAME LIKE '[prefix]%'
RGH
źródło
0

Podejrzewam, że musiałem wykonać niewielkie wyprowadzenie z odpowiedzi Xenpha Yana, ponieważ miałem tabele nie w domyślnym schemacie.

SELECT 'DROP TABLE Databasename.schema.' + TABLE_NAME 
FROM INFORMATION_SCHEMA.TABLES 
WHERE TABLE_NAME LIKE 'strmatch%'
Xaxum
źródło
0

W przypadku tabel tymczasowych możesz spróbować

SELECT 'DROP TABLE "' + t.name + '"' 
FROM tempdb.sys.tables t
WHERE t.name LIKE '[prefix]%'
João Mergulhão
źródło