【问题标题】:TSQL - How to find all tables with a date in the nameTSQL - 如何查找名称中包含日期的所有表
【发布时间】: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 标识为以日期结尾的表名。

标签: sql-server tsql sql-server-2016


【解决方案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 个数字且看起来像日期的表格。它还提供了能够快速删除它们的脚本。

这是在 StackOverflow 上的其他一些答案的帮助下构建的。

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 格式作为日期后缀。
猜你喜欢
  • 2010-09-26
  • 1970-01-01
  • 2020-10-01
  • 1970-01-01
  • 2022-12-24
  • 2011-06-18
  • 2021-09-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多