TSQL - 如何查找名称中包含日期的所有表
Posted
技术标签:
【中文标题】TSQL - 如何查找名称中包含日期的所有表【英文标题】:TSQL - How to find all tables with a date in the name 【发布时间】:2022-01-19 15:18:13 【问题描述】:场景:
我见过临时备份(复制)表格并在名称末尾给出日期的情况。有时,有人忘记删除这些表,或者它们不再需要。
我想要一种方法来查找名称中包含日期的所有表,以便我可以删除任何不需要的表。
【问题讨论】:
请参阅sys.tables
或在 SSMS 中使用对象探索器 (F7)。
一开始就不要使用这样的表格。从任何意义上来说,将一个表的数据复制到另一个表中都不是备份。如果人们想要进行实验,他们应该使用与生产数据库不同的数据库。即使人们使用通用的开发数据库,也很容易创建快照,或者进行真正的备份并在每个人的开发机器上恢复它。或者使用 SSIS 复制测试数据。有很多选择
为了正常的数据管理,所有支持的SQL Server版本都有分区,包括Express和LocalDB
从所有评论的人那里学习,如果我不得不重新做这个问题,我会使用 sys.tables 并自定义 Lukasz 给出的模式来查找所有带有日期的表姓名。要查找所有对象(包括 SP),我可能也会在 sys.objects 上使用类似的模式。感谢您帮助我学习。
根据您的大量示例,您需要将 Mystic_Runes_Hewn_From_The_Living_Rock_On_Shrove_Tuesday_In_The_Year_Of_The_Great_Comet_That_Heralded_The_Demise_Of_Groo
标识为以日期结尾的表名。
【参考方案1】:
使用元数据:
SELECT *
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE '%[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]';
-- pattern at the end should resemble used date format
-- here: my_table20211216
【讨论】:
也可以通过sys.tables
表
这取决于 SQL Server 的版本,对吧?目前似乎未定义。
@xQbert 至少从 2005 年开始就没有了。我不再记得 sys.tables
是在 2000 年还是 7 年存在的。INFORMATION_SCHEMA.TABLES
总是太有限而无法真正使用。
所有“支持”的版本都是对的。在此之前......不要这么想:但谁能记得
@xQbert 任何使用它们的人。 sys.tables
至少从 2005 年就存在了。同样,INFORMATION_SCHEMA
总是太有限了,人们并没有经常使用它,即使在 SQL Server 2000 中【参考方案2】:
如果有帮助的话。
在使用其他人的反馈后,我编写了一个更简单的版本,它只包含表格。原来的答案也有对象(存储过程)。
IF OBJECT_ID('tempdb..#t1') IS NOT NULL DROP TABLE #t1
SELECT @@SERVERNAME AS ServerName
, (SELECT DB_NAME ()) AS DBName
, s.name AS SchemaName
, st.name AS TableName
INTO #t1
FROM sys.tables AS st
INNER JOIN sys.objects AS so ON so.object_id = st.object_id
INNER JOIN sys.schemas AS s ON s.schema_id = st.schema_id
WHERE st.name LIKE '%[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'
ORDER BY st.name;
SELECT t1.ServerName
, t1.DBName
, t1.SchemaName
, t1.TableName
, 'DROP TABLE ' + QUOTENAME(ServerName) + '.' + QUOTENAME(DBName)+'.' + QUOTENAME(SchemaName) + '.' + QUOTENAME(TableName) AS drop_table
FROM #t1 AS t1
【讨论】:
稍微改进一下:'DROP TABLE ' + QUOTENAME(ServerName) + '.' + QUOTENAME(DBName) +'.' + QUOTENAME(SchemaName) + '.' + QUOTENAME(TableName) AS drop_table
QUOTENAME 函数应该优于手动连接 []
感谢@LukaszSzozda,感谢所有帮助我变得更好的人。我希望你有一个美好的一天!
我更新了脚本以反映 Lukasz 的建议。【参考方案3】:
以防对他人有帮助。
这个脚本有 2 个部分。一个执行单个数据库,另一个脚本查看实例上的所有数据库。
脚本会查找所有包含超过 6 个数字且看起来像日期的表格。它还提供了能够快速删除它们的脚本。
这是在 *** 上的其他一些答案的帮助下构建的。
Devart 在此线程上的回答。 Query to get only numbers from a string
Select something that has more/less than x character
/* SINGLE SERVER:
IF OBJECT_ID('tempdb..#t1') IS NOT NULL DROP TABLE #t1
DECLARE @temp TABLE(
ServerName NVARCHAR(1000)
, DatabaseName NVARCHAR(1000)
, SchemaName NVARCHAR(1000)
, TableName NVARCHAR(1000)
);
INSERT INTO @temp(
ServerName
, DatabaseName
, SchemaName
, TableName
)
SELECT @@SERVERNAME AS ServerName
, (SELECT DB_NAME()) AS DatabaseName
, ss.name
, so.name
FROM sys.objects AS so
LEFT OUTER JOIN sys.schemas AS ss ON so.schema_id = ss.schema_id;
SELECT t.ServerName
, t.DatabaseName
, t.SchemaName
, t.TableName
, LEFT(t.subsrt, PATINDEX ('%[^0-9]%', t.subsrt + 't') - 1) AS NumInTblName
INTO #t1
FROM (SELECT subsrt = SUBSTRING (d.TableName, d.pos, LEN (d.TableName))
, d.ServerName
, d.DatabaseName
, d.SchemaName
, d.TableName
FROM (SELECT ServerName
, DatabaseName
, SchemaName
, TableName
, pos = PATINDEX ('%[0-9]%', TableName)
FROM @temp
WHERE PATINDEX ('%[0-9]%', TableName) <> '') d ) t
SELECT
ServerName
, DatabaseName
, SchemaName
, TableName
, NumInTblName
, ISDATE(NumInTblName) AS [ISDate]
, 'DROP TABLE [' + ServerName + '].' + '['+ DatabaseName +'].[' + SchemaName + '].' + '['+ TableName +']' AS DROP_TABLE_Script --+ ' WHERE ' + PotentialDate + ' > DATEADD(day, -365,GETDATE())' AS DROP_TABLE_Script
FROM #t1
WHERE LEN(NumInTblName) > 6
AND ISDATE(NumInTblName) = 1
ORDER BY SchemaName ASC, TableName ASC
*/
--All DB's on an instance.
EXEC sp_MSForEachDB @command1='USE ?;
DECLARE @temp TABLE(
ServerName NVARCHAR(1000)
, DatabaseName NVARCHAR(1000)
, SchemaName NVARCHAR(1000)
, TableName NVARCHAR(1000)
);
INSERT INTO @temp(
ServerName
, DatabaseName
, SchemaName
, TableName
)
SELECT @@SERVERNAME AS ServerName
, (SELECT DB_NAME()) AS DatabaseName
, ss.name
, so.name
FROM sys.objects AS so
LEFT OUTER JOIN sys.schemas AS ss ON so.schema_id = ss.schema_id;
SELECT t.ServerName
, t.DatabaseName
, t.SchemaName
, t.TableName
, LEFT(t.subsrt, PATINDEX (''%[^0-9]%'', t.subsrt + ''t'') - 1) AS NumInTblName
INTO #t1
FROM (SELECT subsrt = SUBSTRING (d.TableName, d.pos, LEN (d.TableName))
, d.ServerName
, d.DatabaseName
, d.SchemaName
, d.TableName
FROM (SELECT ServerName
, DatabaseName
, SchemaName
, TableName
, pos = PATINDEX (''%[0-9]%'', TableName)
FROM @temp
WHERE PATINDEX (''%[0-9]%'', TableName) <> '''') d ) t
SELECT
ServerName
, DatabaseName
, SchemaName
, TableName
, NumInTblName
, ISDATE(NumInTblName) AS [ISDate]
, ''DROP TABLE ['' + ServerName + ''].'' + ''[''+ DatabaseName +''].['' + SchemaName + ''].'' + ''[''+ TableName +'']'' AS DROP_TABLE_Script --+ '' WHERE '' + PotentialDate + '' > DATEADD(day, -365,GETDATE())'' AS DROP_TABLE_Script
FROM #t1
WHERE LEN(NumInTblName) > 6
AND ISDATE(NumInTblName) = 1
ORDER BY SchemaName ASC, TableName ASC
'
【讨论】:
这和问题有什么关系??????对于初学者,您不应该使用这样的表格。所有受支持的 SQL Server 版本和版本都有分区。查找具有特定名称的表就像查询sys.tables
表一样简单。名称以日期结尾的表将在名称末尾有数字,这意味着可以使用name like '%2[0-9][0-9][0-9]
或类似的模式
它列出了名称中包含日期的所有表。
不,它没有。您需要做的就是查询sys.tables
以查找表名以数字结尾的行。不过,您一开始就不应该使用这样的表格
您还假设日期的格式将仅为数字。在我在这个小提琴中创建的 5 个表中,只有 1 个被发现:db<>fiddle 我个人看到了所有 5 个名称的变体。
我没有解决方案(此时),@Jm1。不幸的是,在“现实世界”中,您可能没有那么幸运,因为人们在对象名称中使用了 ISO 格式作为日期后缀。以上是关于TSQL - 如何查找名称中包含日期的所有表的主要内容,如果未能解决你的问题,请参考以下文章