sql >> Database >  >> RDS >> Sqlserver

Hoe een ingesloten SQL 2008-databasebestand te maken als het niet bestaat?

Als ik het was (wanneer ik het ben...):

Je wilt niet echt proberen om databasebestanden te laten werken door ze te kopiëren en bij te voegen - er zijn redenen waarom je dat misschien zou willen, maar ik geloof dat dit uitzonderingen zijn in plaats van regels.

Wat u dus moet doen, is het maken van een script voor de database, d.w.z. om SQL DDL te gebruiken om de database en de tabellen en alle andere dingen in uw schema te maken.

Vrijwel alles wat u nodig hebt om dit te doen, zijn de juiste rechten op de serverinstantie en vervolgens een verbindingsreeks (die u waarschijnlijk los van de server-/instantienaam kunt bouwen).

Vanaf hier:

  1. Is er een database? Zo niet, maak het dan aan.
  2. Als er een database is, is dit dan de juiste schemaversie? Als het te laag is, werk het dan bij of adviseer de gebruiker en ga op een elegante manier terug, afhankelijk van hoe je wilt dat de dingen ook werken. Als het te hoog is, ga dan gewoon terug en geef aan dat een bijgewerkte versie van de applicatie vereist is
  3. Alles is zoals het zou moeten zijn, ga door.

Vanuit een code oogpunt:methode om te bepalen of een database bestaat; methode om een ​​standaard "lege" database aan te maken met een versietabel en een versienummer 0; methoden om het schema naar de huidige versie te brengen door de juiste DDL uit te voeren (we coderen die van ons in C# omdat het meer flexibiliteit biedt, maar u kunt ook DDL-scripts in volgorde uitvoeren).

Bestaat het:

    public virtual bool Exists()
    {
        bool exists = false;

        string masterConnectionString = this.CreateConnectionString(this.Server, this.FailoverServer, "master");

        this.DBConnection.ConnectionString = masterConnectionString;
        this.DBConnection.Open();
        try
        {
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = this.DBConnection;
            cmd.CommandText = "SELECT COUNT(name) FROM sysdatabases WHERE name = @DBName";
            cmd.Parameters.AddWithValue("@DBName", this.DBName);

            exists = (Convert.ToInt32(cmd.ExecuteScalar()) == 1);
        }
        finally
        {
            this.DBConnection.Close();
        }

        return exists;
    }

Maak een nieuwe database:

    public virtual void CreateNew()
    {
        string createDDL = @"CREATE DATABASE [" + this.DBName + "]";

        this.BuildMasterConnectionString();

        this.DBConnection.Open();
        try
        {
            this.ExecuteSQLStmt(createDDL, this.DefaultSQLTimeout, null);
        }
        finally
        {
            this.DBConnection.Close();
        }

        createDDL = @"
                CREATE TABLE AAASchemaVersion 
                (
                    Version         int             NOT NULL,
                    DateCreated     datetime        NOT NULL,
                    Author          nvarchar(30)    NOT NULL,
                    Notes           nvarchar(MAX)   NULL 
                );

                ALTER TABLE AAASchemaVersion ADD CONSTRAINT PK_Version PRIMARY KEY CLUSTERED
                (
                    Version
                );

                INSERT INTO AAASchemaVersion
                    (Version, DateCreated, Author, Notes)
                VALUES
                    (0, GETDATE(), 'James Murphy', 'Empty Database')
            ";

        this.BuildConnectionString();
        this.ConnectionString += ";pooling=false";

        this.DBConnection.Open();
        try
        {
            this.ExecuteSQLStmt(createDDL, this.DefaultSQLTimeout, null);
        }
        catch (Exception ex)
        {
            throw new Exception("Exception while creating / initialising AAASchemaVersion", ex);
        }
        finally
        {
            this.DBConnection.Close();
        }
    }

De update-code is een beetje ingewikkelder, maar voert in feite dit soort dingen uit:

CREATE TABLE AuditUser
(    
    ID                  int IDENTITY(1,1)   NOT NULL,
    UserSourceTypeID    tinyint             NOT NULL,
    DateCreated         smalldatetime       NOT NULL,
    UserName            nvarchar(100)       NOT NULL        
);
ALTER TABLE AuditUser
ADD CONSTRAINT
    PK_AuditUser PRIMARY KEY CLUSTERED
    (
        ID
    ),
    CONSTRAINT [FK_AuditUser_UserSourceType] FOREIGN KEY
    (
        UserSourceTypeID
    ) REFERENCES UserSourceType (
        ID
    );

Alles verpakt in een transactie per update - zodat als de update mislukt, u de database in een bekende goede staat moet achterlaten.

Waarom zou je het op deze manier doen (in code, wat niet zonder proeven is?) Nou, het eindresultaat is een hoge mate van vertrouwen dat het schema waar je app mee praat het schema is waar je app mee verwacht te praten... juiste tabellen, juiste kolommen (in de juiste volgorde, dat is het juiste type en de juiste lengte), etc, etc. en dat dit in de loop van de tijd zo zal blijven.

Excuses als dit een beetje lang is - maar dit is iets waar ik erg enthousiast over ben...



  1. heroku Postgres-fout - operator bestaat niet tijdstempel zonder tijdzone =geheel getal

  2. Hoe kan ik Oracle-queryresultaten per e-mail verzenden. Ik zou het liefst als Excel-bestand bij een e-mail willen voegen.

  3. kopiëren naar tijdelijke tabel duurt lang

  4. PHP-lus die fungeert als cronjob [zorg ervoor dat er slechts één instantie wordt uitgevoerd]