Justin808
Justin808

Reputation: 21522

SQL Server 2000 - How should I go about writing this script?

I wrote out my SQL and ran into an issue, see here.

So I'm asking the proper way to do what I want to do as apposed to, what I consider, a hack of using EXEC. If EXEC is the proper way, then I have issues with SQL but will use it.

I'm writing a SQL script to create/update a database. I have it structured like so:

  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

Logically the above should work, but it doesn't because of the issue I liked to above. So i have the EXEC or the GO option as far as I can tell. EXEC, as a said above, I think is a hack. Its executing a string as SQL, but I'm not using it in a dynamic manner, I have static sql sitting in it - just seems wrong to me. As far as I can tell GO will break it all to, as it resets the variables.

I have the option to re-write the SQL at this point so if I can do it the correct way, I would. I just don't know the correct way I guess.

EDIT (Example script that seems to be working):

I had to break up the SafetyCheck check in the sample above because I can't put a GO inside a IF statement. That made it a lot more ugly.

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

Upvotes: 0

Views: 394

Answers (1)

RichardTheKiwi
RichardTheKiwi

Reputation: 107736

One way to write it is to break all the parts into separate support SPs. Since each SP is compiled itself at the time it executes, there is no static check on the main SP for dependent objects and consistency across all support SPs, within a single batch-block (separated by GO).

Other than that, rewrite your query using dynamic SQL to effect DDL changes, or use GO statements to break them into batches, as you have discovered.

EDIT

The snippet you have shown doesn't work because:

When RunSQL = 0, this part doesn't run

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

Which causes ModifiedDate not to be added to Roles. When I changed RunSQL to 1, the next part doesn't work

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

Because the prior insert put nothing in the table (there is no record in Config)

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

That whole block should just 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

Upvotes: 1

Related Questions