2016-11-01 1 views
0

Ok, der vorherige Thread, den ich gestartet habe, war Archival stored procedures, aber das ist eine Follow-up-Frage dazu. Was ich habe, ist ein Arbeits gespeicherte Prozedur, die eine exakte Kopie der aktiven Datenbank macht, aber wenn ich die alten Säulen des Vormonats entfernen möchten, bläst das Verfahren bis es mit einem Fehler:Follow-up - archivierte gespeicherte Prozedur

Msg 102, Level 15, State 1, Line 3
Incorrect syntax near 'D201609__'.

Hier ist der Code von der vollen proc:

declare @tablename varchar(500) 
declare @sql varchar(5000) 
declare @idname varchar(50) 
declare @tablearchive varchar(500) 
declare @lastmonth nvarchar(MAX) 

SET @lastmonth = 'D' + cast(year(getdate()) as char(4)) + right('0' + cast(month(getdate())-1 as varchar), 2) + '__' 
--Select all the tables which you want to make in archive 

declare tableCursor cursor FAST_FORWARD FOR 
    SELECT table_name 
    FROM INFORMATION_SCHEMA.TABLES 
    WHERE table_name = 'CVECountsByDate' 

--Put your condition, if you want to filter the tables 
--like '%TRN_%' and charindex('Archive',table_name) = 0 and charindex('ErrorLog',table_name) = 0 
--Open the cursor and iterate till end 
OPEN tableCursor 
FETCH NEXT FROM tableCursor INTO @tablename  

WHILE @@FETCH_STATUS = 0 
BEGIN 
    set @tablearchive = @tablename+'_Archive' 

    --check for the table exists, not, create it 
    IF not EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE' AND TABLE_NAME= @tablearchive) 
    BEGIN 
     SET @sql = 'select * into ' + @tablearchive +' from '+ @tablename +' where 1=2' 
     EXEC(@sql) 
    END 

    --check the structure is same, if not, create it 
    IF exists (select column_name from 
      INFORMATION_SCHEMA.COLUMNS where [email protected] and column_name not in (select column_name from INFORMATION_SCHEMA.COLUMNS 
      where [email protected])) 
    BEGIN 
     SET @sql = 'drop table ' + @tablearchive 
     EXEC(@sql) 

     SET @sql = 'select * into ' + @tablearchive +' from '+ @tablename +' where 1=2' 
     EXEC(@sql) 
    END 

    --Check if the table contains, identify column,if yes, then it should be handled in different way 
    --You cannot remove the identity column property through T-SQL 
    --Since the structure of both tables are same, the insert fails, as it cannot insert the identity column 
    --value in the archive table 
    IF EXISTS(SELECT *  FROM information_schema.tables  WHERE table_name = @tablename AND OBJECTPROPERTY(OBJECT_ID(TABLE_NAME), 
      'TableHasIdentity') != 0) 
    BEGIN 
     --Select the identity column name automatically    
     select @idname = column_name 
     from information_schema.columns 
     where columnproperty(object_id(table_name), column_name, 'isidentity') = 1 
      and table_name = @tablearchive 

     --Remove the column 
     SET @sql = 'ALTER TABLE ' + @tablearchive + ' DROP COLUMN ' + @idname 
     EXEC(@sql) 

     --Create the column name again (not as identity) 
     --archive table does require identity column 
     SET @sql = 'ALTER TABLE ' + @tablearchive + ' ADD ' + @idname+ ' INT' 
     EXEC(@sql) 
    END 

    SET @sql = 'insert into ' + @tablearchive +' select * from '+ @tablename 
    EXEC(@sql) 

    FETCH NEXT FROM tableCursor INTO @tablename 

    declare @PrevMonth nvarchar(MAX) = 'D' + cast(year(getdate()) as char(4)) + right('0' + cast(month(getdate())-1 as varchar), 2) + '__' 
    DECLARE @DynSql nvarchar(MAX) = 'ALTER TABLE ' + @tablename + ' DROP COLUMNS IF EXISTS 
    (SELECT COLUMN_NAME Columns FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ' + @tablename + ' 
AND COLUMN_NAME LIKE ' + @PrevMonth + '' 

    SELECT (@DynSql) 
    EXEC(@DynSql) 
END 

CLOSE tableCursor 
DEALLOCATE tableCursor 

So genau wie bekomme ich die Spalte Entfernung Teil meiner Proc zu arbeiten?

+3

Ich glaube, Sie Ihren Ansatz zu einer Lösung überdenken sollten, wenn Sie jeden Monat mit dem Schema haben zu Chaos nicht. Alles scheint mir ein schlechtes Design zu sein. –

+0

Ich stimme @RicardoC zu. Wenn Sie das Schema jeden Monat ändern müssen, ist dies ein deutlicher Hinweis darauf, dass etwas mit Ihrem Design nicht stimmt. Datenbanken sind so konzipiert, dass sie Daten speichern und nicht wie eine Puppe ständig manipuliert werden können. –

+0

Dieses Verfahren habe ich von jemand anderem bekommen. Sie empfehlen also, alle diese Spalten in der Haupttabelle zu belassen? Ist Ihnen bewusst, dass ich jeden Tag numerische Datensätze importiere, über 3000? Vertrauen Sie mir, wenn ich Ihnen sage, dass ich sehr sorgfältig daran gedacht habe, Daten nur Zeile für Zeile zu übergeben, aber die Datenbanktabelle würde sehr schnell sehr groß werden. Meine Sorge bezieht sich auf CVE_Id Nummer und dann nur die Anzahl in die Datumsspalte. Es sei denn jemand von euch hat eine andere Schema Idee. – bbcompent1

Antwort

0

Meine Frage, die offenbar ich für Art und Weise starrte zu lange lesen:

ALTER TABLE CVECountsByDate DROP COLUMNS IF EXISTS (SELECT COLUMN_NAME 
Columns FROM INFORMATION_SCHEMA.COLUMNS 
WHERE TABLE_NAME = CVECountsByDate AND COLUMN_NAME LIKE 'D201609__' 

Dies ist eigentlich eine Ausgabe wie diese haben soll:

ALTER TABLE CVECountsByDate DROP COLUMNS IF EXISTS (SELECT COLUMN_NAME 
Columns FROM INFORMATION_SCHEMA.COLUMNS 
WHERE TABLE_NAME = 'CVECountsByDate' AND COLUMN_NAME LIKE 'D201609__' 

Ich habe vergessen, die Tabellennamen mit Anführungszeichen zu umgeben. Und ja, ich habe einen roten Handabdruck in der Mitte meiner Stirn, als es mir dämmerte.

Also die Abfrage selbst lautet wie folgt:

DECLARE @DynSql nvarchar(MAX) = 'ALTER TABLE CVECountsByDate DROP 
    COLUMNS IF EXISTS (SELECT COLUMN_NAME Columns FROM 
    INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '''CVECountsByDate''' AND 
    COLUMN_NAME LIKE ''' + @PrevYear + ''')'