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 - 如何查找名称中包含日期的所有表的主要内容,如果未能解决你的问题,请参考以下文章

将工作表的副本另存为 CSV,并在保存名称中包含日期

Flyway-在名称中包含指定后缀的所有表中添加一列

查找名称包含字符串的所有文件[关闭]

SQL如何查找和删除MYSQL数据库中包含特定字符串的记录

查找名称中包含奇数字符的记录

如何编写一个查询以从SQL Server中包含类似名称的多个表中获取数据