2011-01-31 62 views
0

我寫出了我的SQL並遇到問題,請參見hereSQL Server 2000 - 我該怎麼寫這個腳本?

因此,我要求正確的方法來做我想做的事情,因爲我認爲這是使用EXEC的黑客行爲。如果EXEC是正確的方式,那麼我有SQL的問題,但會使用它。

我正在寫一個SQL腳本來創建/更新數據庫。我有它的結構像這樣:

Declare SafetyCheck=0 
    Declare DBVersion=0 
    Declare NewInstall=0 
    Declare DropTables=0 

    IF SafetyCheck=1 
    Begin 
    IF DropTables = 1 
     Drop all tables in the database 

    IF Config table doesn't exist 
    Begin 
     Create the Config Table 
     NewInstall = 1 
    End 
    IF Other Table doesn't exist 
     Create the other table 
    IF Other Table doesn't exist 
     Create the other table 

    DBVersion = CheckTheDBVersion 
    IF DBVersion is old 
    Begin 
     Alter tables to make them +1 version higher 
     Insert some stuff 
    End 

    DBVersion = CheckTheDBVersion 
    IF DBVersion is old 
    Begin 
     Alter tables to make them +1 version higher 
     Insert some stuff 
    End 

    IF NewInstall = 1 
    Begin 
     Insert default data 
    End 
    End 

按道理上面應該工作,但它沒有我喜歡上面的問題,因爲。據我所知,我有EXEC或GO選項。正如上面所說的,EXEC,我認爲是一種破解。它執行一個字符串作爲SQL,但我沒有以動態的方式使用它,我有靜態SQL坐在它 - 只是似乎錯了我。據我所知,GO會將所有內容都打破,因爲它會重置變量。

我現在可以選擇重寫SQL,所以如果我能以正確的方式做到這一點,我會的。我只是不知道我猜的正確方法。

EDIT(示例腳本似乎是工作):

我不得不分手上面,因爲我不能把一個GO一個IF語句內的樣品中的SafetyCheck檢查。這使得它更難看。

-- -- -- 
-- Run this once to create the initial tables 
-- -- -- 
CREATE TABLE Config (
    ID   [int] IDENTITY(1,1) NOT NULL, 
    [Key]  [nvarchar](255) NOT NULL, 
    Value  [nvarchar](255) NOT NULL 
) 
ALTER TABLE Config ADD PRIMARY KEY (ID) 
CREATE TABLE Roles (
    ID    [int] IDENTITY(1,1) NOT NULL, 
    Name   [nvarchar](25) NOT NULL, 
    Created   [DateTime] NOT NULL 
) 
ALTER TABLE Roles ADD PRIMARY KEY (ID) 

-- -- -- 
-- Below, this is the script thats causing errors 
-- -- -- 

IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '#v') 
    DROP TABLE #v 
CREATE TABLE #v (n char(30),v char(30)) 

INSERT INTO #v (n,v) VALUES ('RunSQL', '1')   -- Set to 1 or this does nothing 
INSERT INTO #v (n,v) VALUES ('DropTables', '0')  -- Set to 1 to drop existing tables 
                -- dont do this for an upgrade 
                -- dont do this is there are custom tables 

GO 
IF (SELECT v FROM #v WHERE n='RunSQL') = 0 
BEGIN 
    SELECT 'Nothing has been done. Read First, Run Later' AS Error 
END 


IF (SELECT v FROM #v WHERE n='RunSQL') = 1 
BEGIN 
    IF (SELECT v FROM #v WHERE n='DropTables') = 1 
    BEGIN 
     -- Remove all tables if they exist 
     EXEC sp_MSforeachtable @command1 = 'DROP TABLE ?' 
    END 
END 
GO 

IF (SELECT v FROM #v WHERE n='RunSQL') = 1 
BEGIN 
    IF NOT EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Config') 
    BEGIN 
     CREATE TABLE Config (
      ID   [int] IDENTITY(1,1) NOT NULL, 
      [Key]  [nvarchar](255) NOT NULL, 
      Value  [nvarchar](255) NOT NULL 
     ) 
     ALTER TABLE Config ADD PRIMARY KEY (ID) 

     -- Assume this is a new database 
     INSERT INTO Config ([Key], Value) VALUES ('DBVersion', '3') 
    END 

    IF NOT EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Roles') 
    BEGIN 
     CREATE TABLE Roles (
      ID    [int] IDENTITY(1,1) NOT NULL, 
      Name   [nvarchar](25) NOT NULL, 
      Created   [DateTime] NOT NULL, 
      ModifiedDate [DateTime] NOT NULL 
     ) 
     ALTER TABLE Roles ADD PRIMARY KEY (ID) 
    END 
END 
GO 

-- Lookup the current verision of the database 
IF (SELECT v FROM #v WHERE n='RunSQL') = 1 
BEGIN 
    INSERT INTO #v (n,v) SELECT 'CMSDBVersion', Value FROM Config WHERE [Key]='DBVersion' 
END 
GO 

-- Update old tables to be like the new ones 
IF (SELECT v FROM #v WHERE n='RunSQL') = 1 
BEGIN 
    IF (SELECT COUNT(v) FROM #v WHERE n='CMSDBVersion') = 0 
    BEGIN 
     -- Add newer fields to exiting tables 
     ALTER TABLE Roles ADD ModifiedDate DateTime; 
     INSERT INTO Config ([Key], Value) Values ('DBVersion', '3') 
    END 
END 
IF (SELECT v FROM #v WHERE n='RunSQL') = 1 
BEGIN 
    INSERT INTO #v (n,v) SELECT 'CMSDBVersion', Value FROM Config WHERE [Key]='DBVersion' 
END 
GO 

IF (SELECT v FROM #v WHERE n='RunSQL') = 1 
BEGIN 
    IF (SELECT v FROM #v WHERE n='CMSDBVersion') = '3' 
    BEGIN 
     -- Add/Update the standard rules 
     IF NOT EXISTS (SELECT * FROM Roles WHERE Name='CMS User Admin') 
      INSERT INTO Roles (Name, Created, ModifiedDate) VALUES ('CMS User Admin', GETDATE(), GETDATE()) 
    END 
END 
GO 

-- remove the temp table 
DROP TABLE #v 
+1

@marc_S - thanks,fixed – Justin808 2011-01-31 21:51:41

回答

1

編寫它的一種方法是將所有零件拆分成單獨的支持SP。由於每個SP在執行時都會自行編譯,因此在一個批處理塊(由GO分隔)內,不存在對所有支持SP中的從屬對象的主SP和一致性的靜態檢查。

除此之外,使用動態SQL重寫您的查詢以實現DDL更改,或使用GO語句將它們分成批次,就像您發現的那樣。

編輯

你已經證明不起作用,因爲該段:

當RunSQL = 0,該部分不運行

-- Update old tables to be like the new ones 
IF (SELECT v FROM #v WHERE n='RunSQL') = 1 

導致ModifiedDate不被添加到角色。當我改變RunSQL爲1,下一個部分不工作

IF (SELECT v FROM #v WHERE n='CMSDBVersion') = '' 

因爲現有的插入件把沒有在表中(沒有在配置沒有記錄)

INSERT INTO #v (n,v) SELECT 'CMSDBVersion', Value FROM Config WHERE [Key]='DBVersion' 
GO 

這整塊應該只是是

-- Update old tables to be like the new ones 
    IF NOT EXISTS (select * from syscolumns where name='ModifiedDate' and ID = OBJECT_ID('Roles')) 
    BEGIN 
     -- Add newer fields to exiting tables 
     ALTER TABLE Roles ADD ModifiedDate DateTime; 
     UPDATE Config SET Value = '3' WHERE [Key]='DBVersion' 
    END 
+0

但是,如何在不重置所有變量的情況下使用GO? – Justin808 2011-01-31 21:06:29