-1

Scenario:

I've seen cases where tables are temporarily backed up(copied) and given a date on the end of the name. Sometimes, someone forgets to remove these tables or they are just no longer needed.

I wanted a way to find any tables that had a date in the name so I could delete any unneeded tables.

JM1
  • 1,595
  • 5
  • 19
  • 41
  • see `sys.tables` or use object exploter (F7) in SSMS. – Stu Dec 16 '21 at 14:29
  • 1
    Don't use such tables to begin with. Copying the data of one table into another is not a backup by any sense of the word. If people want to experiment they should work on a *different* database than the production database. Even if people work with a common development database, it's easy to create snapshots, or take a real backup and restore it on each person's development machine. Or use SSIS to copy the test data. There are a lot of options – Panagiotis Kanavos Dec 16 '21 at 14:30
  • For normal data management, all supported SQL Server versions have partitions, even Express and LocalDB – Panagiotis Kanavos Dec 16 '21 at 14:30
  • 1
    In learning from all the people that commented, if I had to do this question over again, I would use sys.tables and customize the pattern given by Lukasz to find all the tables with a date in the name. To find all objects (including SP's) I would likely use a similar pattern on sys.objects as well. Thanks for helping me learn. – JM1 Dec 16 '21 at 14:48
  • Based on your extensive examples you would need to identify `Mystic_Runes_Hewn_From_The_Living_Rock_On_Shrove_Tuesday_In_The_Year_Of_The_Great_Comet_That_Heralded_The_Demise_Of_Groo` as a table name ending in a date. – HABO Dec 16 '21 at 19:12

3 Answers3

3

Using metadata:

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
Lukasz Szozda
  • 162,964
  • 23
  • 234
  • 275
  • 2
    Also possible through the `sys.tables` table – Panagiotis Kanavos Dec 16 '21 at 14:26
  • That would depend on the version of SQL Server right? Which presently appears to be undefined. – xQbert Dec 16 '21 at 14:30
  • @xQbert not since 2005 at least. I no longer remember is `sys.tables` existed in 2000 or 7. `INFORMATION_SCHEMA.TABLES` was *always* too limited for real use. – Panagiotis Kanavos Dec 16 '21 at 14:31
  • all "Supported" versions you're right. Before that... don't think so: but who can remember – xQbert Dec 16 '21 at 14:33
  • @xQbert anyone who used them. `sys.tables` existed at least since 2005. Again, `INFORMATION_SCHEMA` was *always* too limited and people didn't use it a lot, even in SQL Server 2000 – Panagiotis Kanavos Dec 16 '21 at 14:35
  • affirmitive. Just went back and looked at several documents. for some reason I thought it was just sysobjects under a different schema. – xQbert Dec 16 '21 at 14:40
1

In case it's helpful.

After using the feedback from others, I wrote a simpler version that gets just tables. The original answer also had objects(stored procedures).

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
JM1
  • 1,595
  • 5
  • 19
  • 41
  • 1
    To improve it a bit: `'DROP TABLE ' + QUOTENAME(ServerName) + '.' + QUOTENAME(DBName) +'.' + QUOTENAME(SchemaName) + '.' + QUOTENAME(TableName) AS drop_table` [QUOTENAME](https://learn.microsoft.com/en-us/sql/t-sql/functions/quotename-transact-sql?view=sql-server-ver15) function should be preferred over manual concatenating `[]` – Lukasz Szozda Dec 16 '21 at 17:06
  • 1
    Thanks @LukaszSzozda, I am grateful for everyone that's helped me get better. I hope you have a great day! – JM1 Dec 16 '21 at 17:25
  • I updated the script to reflect Lukasz's suggestion. – JM1 Dec 16 '21 at 17:38
0

In case it's helpful to others.

This script has 2 parts. One does a single database and the other script looks at all databases on an instance.

The script(s) find all tables that have more than 6 numbers in them and look like a date. It also provides the script to be able to quickly drop them.

This was constructed with the help of a few other answers on StackOverflow.

Devart's answer on this thread. 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
'
JM1
  • 1,595
  • 5
  • 19
  • 41
  • 1
    What does this have to do with the question??????? For starters, you shouldn't be using such tables. All supported SQL Server versions and editions have partitions. Finding tables with a specific name is as simple as querying the `sys.tables` table. A table whose name ends in a date would have numbers at the end of the name, which means `name like '%2[0-9][0-9][0-9]` or a similar pattern can be used – Panagiotis Kanavos Dec 16 '21 at 14:22
  • It lists all tables that have a date in the name. – JM1 Dec 16 '21 at 14:24
  • No it doesn't. All you need to do is query `sys.tables` for rows where the table name ends with digits. You shouldn't be using such tables in the first place though – Panagiotis Kanavos Dec 16 '21 at 14:25
  • 1
    You also *assume* that the format of the date will be numeric digits only. Of the 5 tables I create in this fiddle, only 1 of them is found: [db<>fiddle](https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=26e903c0ce3a6670291ef59fa7be67e3) I have, personally, seen variations of all 5 of those names. – Thom A Dec 16 '21 at 14:28
  • Interesting @Larnu, how would you account for those differences? I think in my particular scenario, they would all be numeric, but it would be better to account for non-numerics. – JM1 Dec 16 '21 at 14:30
  • 1
    I don';t have a solution (at this time), @Jm1 . Just that in the "real world" unfortunately you may not be as lucky for people have used the ISO format as a date suffix in their object names. – Thom A Dec 16 '21 at 14:32
  • @JM1 in short, don't use such tables. There are far cleaner ways to copy data for testing, development or regular data management – Panagiotis Kanavos Dec 16 '21 at 14:34
  • @PanagiotisKanavos, thanks for the feedback in all your comments. I'm still learning and I intend to keep getting better. However, it's not always my choice in how tables get created, my task is to keep them cleaned up after the fact. – JM1 Dec 16 '21 at 14:36