2011-01-31 2 views
0

Я написал свой SQL и столкнулся с проблемой, см. here.SQL 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 (Пример сценария, который, кажется, работает):

мне пришлось разбить чек SafetyCheck в приведенном выше примере, потому что я не могу поставить GO в заявлении IF. Это сделало его намного более уродливым.

-- -- -- 
-- 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 - спасибо, исправлено – Justin808

ответ

1

Один из способов написать это разбить все части на отдельные поддерживающие SP. Поскольку каждый SP скомпилирован сам по себе во время его выполнения, статическая проверка основного SP для зависимых объектов и согласованность во всех поддерживающих SP в пределах одного пакетного блока (разделена GO).

Кроме этого, перепишите запрос с использованием динамического SQL для изменения DDL или используйте инструкции GO, чтобы разбить их на партии, как вы обнаружили.

EDIT

Сниппет вы показали не работает, потому что:

Когда 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') = '' 

Поскольку перед вставкой ничего не поместите в таблице (нет записи в Config)

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

Весь этот блок должен просто be

-- 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

+0

@Justin - Если это в SP, вы даже не можете иметь инструкции GO, поэтому используйте с поддержкой SP. Если нет, и это всего лишь специальная партия, сохраните переменные в таблице temp и обратитесь к ним с помощью '(выберите whovar_as_column из #tmpstorage)' – RichardTheKiwi

+0

@cyberkiwi - это просто сценарий, который я загружаю в студию управления и запустить.Я переместил все переменные во временную таблицу, и я переструктурировал SQL для размещения GO в конце блоков кода, так как я кота помещал GO внутри Begin/End, но я все еще получаю ошибки, потому что SQL не пропускается, если IF не работает. – Justin808