Как удалить все таблицы, имена которых начинаются с заданной строки?
Я думаю, что это можно сделать с помощью динамического SQL и таблиц INFORMATION_SCHEMA.


SELECT 'DROP TABLE "' + TABLE_NAME + '"'
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE '[prefix]%'
Это сгенерирует сценарий.
Добавление предложения для проверки существования таблицы перед удалением:
SELECT 'IF OBJECT_ID(''' +TABLE_NAME + ''') IS NOT NULL BEGIN DROP TABLE [' + TABLE_NAME + '] END;'
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE '[prefix]%'
MYSQL: SELECT concat ('DROP TABLE', TABLE_NAME, ";") as data FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME LIKE '[prefix]%' --- для тех, кто, как я, нашел эту тему
Результат также содержит просмотры
Не забудьте экранировать _, если это часть вашего префикса, например. WHERE TABLE_NAME LIKE 'em\_%' ESCAPE '\';
Это создает сценарий, но как его выполнить?
Потрясающие! Мне очень нравится подход «сначала сценарий», так что я мог видеть, что упадет, а не просто выполнить. Супер полезное спасибо !!
В этом рабочем процессе выполните сценарий, выделив полный выходной столбец, скопируйте и вставьте его в окно запроса. Идея состоит в том, чтобы вручную просмотреть каждую строку и, возможно, изменить перед выполнением отбрасывания.
Ответ Ксенф Ян был намного чище, чем мой, но вот мой все равно.
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
Просто замените tableName на символы, которые вы хотите использовать для поиска.
Вам может потребоваться изменить запрос, чтобы включить владельца, если в базе данных их несколько.
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
Это чище, чем использование двухэтапного подхода «генерация скрипта плюс запуск». Но одним из преимуществ генерации сценария является то, что он дает вам возможность полностью просмотреть то, что будет запускаться, прежде чем оно будет запущено на самом деле.
Я знаю, что если бы я собирался сделать это с производственной базой данных, я был бы максимально осторожен.
Редактировать Пример кода исправлен.
Возможно, вам придется запускать этот сценарий несколько раз из-за ограничений внешнего ключа между главной и подробной таблицами.
В SQL Server 2005 мне пришлось изменить две последние строки на close cmds; deallocate cmds.
У меня это не сработало. Ответ на этот вопрос сработал: stackoverflow.com/questions/5116296/…
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
select 'DROP TABLE ' + name from sysobjects
where type = 'U' and sysobjects.name like '%test%'
- Test - это имя таблицы
на самом деле это ничего не выполняет, просто возвращает кучу команд.
Это позволит вам расположить таблицы в порядке внешнего ключа и избежать отбрасывания некоторых таблиц, созданных SQL Server. Значение t.Ordinal разделит таблицы на уровни зависимостей.
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
Спасибо stackoverflow.com/questions/352176/…
Быстрое исправление: TableName несколько раз появляется в предложениях WHERE, и его следует заменить на OBJECT_NAME (so.object_id). Хороший сценарий!
SELECT 'if object_id(''' + TABLE_NAME + ''') is not null begin drop table "' + TABLE_NAME + '" end;'
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE '[prefix]%'
Я подозреваю, что мне пришлось сделать небольшой вывод по ответу Ксенфа Яна, потому что у меня были таблицы, не входящие в схему по умолчанию.
SELECT 'DROP TABLE Databasename.schema.' + TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE 'strmatch%'
В Oracle XE это работает:
SELECT 'DROP TABLE "' || TABLE_NAME || '";'
FROM USER_TABLES
WHERE TABLE_NAME LIKE 'YOURTABLEPREFIX%'
Или, если вы хотите также убрать ограничения и освободить место, используйте это:
SELECT 'DROP TABLE "' || TABLE_NAME || '" cascade constraints PURGE;'
FROM USER_TABLES
WHERE TABLE_NAME LIKE 'YOURTABLEPREFIX%'
Это сгенерирует кучу операторов DROP TABLE cascade constraints PURGE ...
Для VIEWS используйте это:
SELECT 'DROP VIEW "' || VIEW_NAME || '";'
FROM USER_VIEWS
WHERE VIEW_NAME LIKE 'YOURVIEWPREFIX%'
Сработало отлично. Пришлось удалить 61 037 пустых таблиц из базы данных, используемой для контроля качества. Я использовал пример каскадных ограничений. Сгенерировал вывод, затем скопировал все в сценарий и запустил его. Принял навсегда, но это сработало как шарм! Спасибо!
Я увидел этот пост, когда искал инструкцию mysql для удаления всех таблиц WordPress на основе @Xenph Yan, вот что я в итоге сделал:
SELECT CONCAT( 'DROP TABLE `', TABLE_NAME, '`;' ) AS query
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE 'wp_%'
это даст вам набор запросов на удаление для всех таблиц, начинающийся с wp_
Вот мое решение:
SELECT CONCAT('DROP TABLE `', TABLE_NAME,'`;')
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE 'TABLE_PREFIX_GOES_HERE%';
И, конечно же, вам нужно заменить TABLE_PREFIX_GOES_HERE своим префиксом.
EXEC sp_MSforeachtable 'if PARSENAME("?",1) like ''%CertainString%'' DROP TABLE ?'
Редактировать:
sp_MSforeachtable недокументирована, поэтому не подходит для производства, поскольку ее поведение может варьироваться в зависимости от версии MS_SQL.
Потрясающий однострочник! Это должно быть поставлено на первое место.
В случае временных таблиц вы можете попробовать
SELECT 'DROP TABLE "' + t.name + '"'
FROM tempdb.sys.tables t
WHERE t.name LIKE '[prefix]%'
Это сработало для меня.
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;
Я хотел бы опубликовать свое предложение о решении, которое DROP (а не просто генерирует и выбирает команды drop) все таблицы на основе подстановочного знака (например, «table_20210114») старше определенного количества дней.
DECLARE
@drop_command NVARCHAR(MAX) = '',
@system_time date,
@table_date nvarchar(8),
@older_than int = 7
Set @system_time = (select getdate() - @older_than)
Set @table_date = (SELECT CONVERT(char(8), @system_time, 112))
SELECT @drop_command += N'DROP TABLE ' + QUOTENAME(SCHEMA_NAME(schema_id)) + '.' + QUOTENAME([Name]) + ';'
FROM <your_database_name>.sys.tables
WHERE [Name] LIKE 'table_%' AND RIGHT([Name],8) < @table_date
SELECT @drop_command
EXEC sp_executesql @drop_command
Я мог бы добавить, чтобы убрать скобки при замене «префикса» на ваш целевой префикс.