sql >> Databasteknik >  >> RDS >> Sqlserver

Hur skapar man en inbäddad SQL 2008-databasfil om den inte finns?

Om det var jag (när det är jag...):

Du vill inte särskilt försöka få databasfiler att fungera genom att kopiera dem och bifoga dem - det finns anledningar till att du kanske vill det, men jag tror att det är undantag snarare än regler.

Det du behöver göra är att skapa skript för databasen, dvs att använda SQL DDL för att skapa databasen och tabellerna och alla andra saker i ditt schema.

I stort sett allt du behöver för att du ska kunna göra detta är lämpliga rättigheter till serverinstansen och sedan en anslutningssträng (som du förmodligen kan bygga förutom serverns/instansens namn).

Härifrån:

  1. Finns det en databas? Om inte, skapa den.
  2. Om det finns en databas, är det rätt schemaversion? Om det är för lågt, antingen uppdatera det eller ge användaren råd och backa graciöst beroende på hur du vill att saker och ting ska fungera. Om det är för högt, gå bara tillbaka och meddela att en uppdaterad version av programmet krävs
  3. Allt är som det ska, fortsätt.

Ur kodsynpunkt:metod för att avgöra om en databas existerar; metod för att skapa en standard "tom" databas med en versionstabell och ett versionsnummer 0; metoder för att få upp schemat till den aktuella versionen genom att köra lämplig DDL (vi kodar vår till C# eftersom det ger mer flexibilitet men du kan lika gärna köra DDL-skript i sekvens).

Finns det:

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

Skapa en ny databas:

    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();
        }
    }

Uppdateringskoden är lite mer komplex men kör i princip saker som detta:

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

Allt samlat i en transaktion per uppdatering - så att om uppdateringen misslyckas bör du lämna databasen i ett känt tillstånd.

Varför göra det på detta sätt (i kod, som inte är utan tester?) och slutresultatet är en hög grad av förtroende för att schemat som din app pratar med är det schema som din app förväntar sig att prata med... rätt tabeller, högerkolumner (i rätt ordning, som är rätt typ och rätt längd), etc, etc. och att så kommer att fortsätta att vara fallet med tiden.

Ber om ursäkt om det här är lite långt - men det här är något jag är ganska sugen på...



  1. Åtgärda luckor i mysql-tabellrad-ID efter att vi tagit bort några av dem

  2. Migrera från MySQL till PostgreSQL

  3. Icke-superanvändare kan inte ansluta om servern inte begär ett lösenord när dblink används

  4. MySQL Cross Table Constraint