web-dev-qa-db-ja.com

SQL Serverのelseブロックにプロシージャを作成する

データベースとそのテーブル、ストアドプロシージャ、ビューなどを生成するSQLスクリプトがあります。次のスクリプトを使用して、データベースとすべてのものを生成しました。テーブルを生成できましたが、ストアドプロシージャでエラーが発生します。

'CREATE/ALTER PROCEDURE' must be the first statement in a query batch.'

これがコードです。 if/elseブロックなので、goステートメントを使用できません。データベースが存在するかどうかを確認し、適切なアクションを実行します。誰もがその解決策を持っていますか?

編集後:

    IF EXISTS(SELECT name FROM sys.databases WHERE name = 'SampleDB')
        begin
        PRINT 'Exist.'
        end
        Else
        begin
        CREATE DATABASE SampleDB
        exec sp_dboption N'SampleDB', N'autoshrink', N'false'
        exec sp_dboption N'SampleDB', N'ANSI null default', N'false'
        exec sp_dboption N'SampleDB', N'recursive triggers', N'false'
        exec sp_dboption N'SampleDB', N'ANSI nulls', N'false'
        exec sp_dboption N'SampleDB', N'concat null yields null', N'false'
        exec sp_dboption N'SampleDB', N'cursor close on commit', N'false'
        exec sp_dboption N'SampleDB', N'default to local cursor', N'false'
        exec sp_dboption N'SampleDB', N'quoted identifier', N'false'
        exec sp_dboption N'SampleDB', N'ANSI warnings', N'false'
        exec sp_dboption N'SampleDB', N'auto create statistics', N'true'
        exec sp_dboption N'SampleDB', N'auto update statistics', N'true'

        DECLARE @sql nvarchar(MAX)
        SET @sql='
        use SampleDB

        CREATE TABLE [dbo].[BrandMaster] (
        [BrandId] [int] IDENTITY (1, 1) CONSTRAINT [PK_BrandMaster] PRIMARY KEY NOT NULL ,
        [BrandName] [nvarchar] (50) NOT NULL ,
        [BrandStatus] [bit] NOT NULL
        )
        CREATE TABLE [dbo].[BrandProductMaster] (
        [BrandProductId] [int] IDENTITY (1, 1) CONSTRAINT [PK_BrandProductMaster] PRIMARY KEY NOT NULL ,
        [ProductId] [int] NOT NULL ,
        [BrandId] [int] NOT NULL ,
        [Units] [nvarchar] (15) NULL ,
        [Status] [bit] NOT NULL
        )
        CREATE TABLE [dbo].[BrokerMaster] (
        [BrokerId] [int] IDENTITY (1, 1) CONSTRAINT [PK_BrokerMaster] PRIMARY KEY NOT NULL ,
        [BrokerName] [nvarchar] (100) NOT NULL ,
        [BrokerPercentage] [float] NOT NULL ,
        [BrokerAddress] [nvarchar] (100) NULL ,
        [BrokerTelephoneNo] [bigint] NULL ,
        [BrokerMobileNo] [bigint] NULL ,
        [BrokerFaxNo] [bigint] NULL ,
        [BrokerEmailId] [nvarchar] (75) NULL ,
        [BrokerStatus] [bit] NOT NULL
        )
        INSERT INTO [dbo].[BrokerMaster] ([BrokerName],[BrokerPercentage],[BrokerAddress],[BrokerEmailId],[BrokerStatus]) VALUES (''No Broker'',0.0,'''','''',1)
        ...........
.............
............
............../After creating list of tables,here goes for stored procedure and views


       EXECUTE (''CREATE PROCEDURE [dbo].[usp_ExtractAllBrokers] AS Select BrokerId, BrokerName, BrokerStatus,BrokerPercentage From BrokerMaster'')
    EXECUTE (''CREATE VIEW dbo.View_UserMaster AS SELECT UserId, UserCompanyId, UserFullName, Username,[Password],CASE UserStatus WHEN 1 THEN ''Active'' WHEN 0 THEN ''InActive'' END AS UserStatus, UserMobileNo, UserEmailId, CASE BrokerMaster WHEN 1 THEN ''Y'' WHEN 0 THEN ''N'' END AS BrokerMaster,CASE CompanyMaster WHEN 1 THEN ''Y'' WHEN 0 THEN ''N'' END AS CompanyMaster,CASE CustomerMaster WHEN 1 THEN ''Y'' WHEN 0 THEN ''N'' END AS CustomerMaster,CASE TaxMaster WHEN 1 THEN ''Y'' WHEN 0 THEN ''N'' END AS TaxMaster, CASE UserMaster WHEN 1 THEN ''Y'' WHEN 0 THEN ''N'' END AS UserMaster,CASE VendorMaster WHEN 1 THEN ''Y'' WHEN 0 THEN ''N'' END AS VendorMaster,CASE ProductMaster WHEN 1 THEN ''Y'' WHEN 0 THEN ''N'' END AS ProductMaster,CASE Purchase WHEN 1 THEN ''Y'' WHEN 0 THEN ''N'' END AS Purchase, CASE Sales WHEN 1 THEN ''Y'' WHEN 0 THEN ''N'' END AS Sales,CASE Reporting WHEN 1 THEN ''Y'' WHEN 0 THEN ''N'' END AS Reporting, UserCreatedOn FROM dbo.UserMaster'')

    exec sp_addextendedproperty N''MS_DiagramPane1'', N''[0E232FF0-B466-11cf-A24F-00AA00A3EFFF, 1.00]
    Begin DesignProperties = 
       Begin PaneConfigurations = 
          Begin PaneConfiguration = 0
             NumPanes = 4
             Configuration = "(H (1[40] 4[20] 2[20] 3) )"
          End
          Begin PaneConfiguration = 1
             NumPanes = 3
             Configuration = "(H (1 [50] 4 [25] 3))"
          End
          Begin PaneConfiguration = 2
             NumPanes = 3
             Configuration = "(H (1 [50] 2 [25] 3))"
          End
          Begin PaneConfiguration = 3
             NumPanes = 3
             Configuration = "(H (4 [30] 2 [40] 3))"
          End
          Begin PaneConfiguration = 4
             NumPanes = 2
             Configuration = "(H (1 [56] 3))"
          End
          Begin PaneConfiguration = 5
             NumPanes = 2
             Configuration = "(H (2 [66] 3))"
          End
          Begin PaneConfiguration = 6
             NumPanes = 2
             Configuration = "(H (4 [50] 3))"
          End
          Begin PaneConfiguration = 7
             NumPanes = 1
             Configuration = "(V (3))"
          End
          Begin PaneConfiguration = 8
             NumPanes = 3
             Configuration = "(H (1[56] 4[18] 2) )"
          End
          Begin PaneConfiguration = 9
             NumPanes = 2
             Configuration = "(H (1 [75] 4))"
          End
          Begin PaneConfiguration = 10
             NumPanes = 2
             Configuration = "(H (1[66] 2) )"
          End
          Begin PaneConfiguration = 11
             NumPanes = 2
             Configuration = "(H (4 [60] 2))"
          End
          Begin PaneConfiguration = 12
             NumPanes = 1
             Configuration = "(H (1) )"
          End
          Begin PaneConfiguration = 13
             NumPanes = 1
             Configuration = "(V (4))"
          End
          Begin PaneConfiguration = 14
             NumPanes = 1
             Configuration = "(V (2))"
          End
          ActivePaneConfig = 0
       End
       Begin DiagramPane = 
          Begin Origin = 
             Top = 0
             Left = 0
          End
          Begin Tables = 
             Begin Table = "UserMaster"
                Begin Extent = 
                   Top = 6
                   Left = 38
                   Bottom = 121
                   Right = 198
                End
                DisplayFlags = 280
                TopColumn = 1
             End
          End
       End
       Begin SQLPane = 
       End
       Begin DataPane = 
          Begin ParameterDefaults = ""
          End
          Begin ColumnWidths = 20
             Width = 284
             Width = 1500
             Width = 1500
             Width = 1500
             Width = 1500
             Width = 1500
             Width = 1500
             Width = 1500
             Width = 1500
             Width = 1500
             Width = 1500
             Width = 1500
             Width = 1500
             Width = 1500
             Width = 1500
             Width = 1500
             Width = 1500
             Width = 1500
             Width = 1500
             Width = 1500
          End
       End
       Begin CriteriaPane = 
          Begin ColumnWidths = 11
             Column = 3210
             Alias = 2595
             Table = 1170
             Output = 720
             Append = 1400
             NewValue = 1170
             SortType = 1350
             SortOrder = 1530
             GroupBy = 1350
             Filter = 1350
             Or = 2025
             Or = 1350
             Or = 1350
          End
       End
    End
    '', N''user'', N''dbo'', N''view'', N''View_UserMaster''
    exec sp_addextendedproperty N''MS_DiagramPaneCount'', 1, N''user'', N''dbo'', N''view'', N''View_UserMaster''
    '
    EXECUTE sp_executesql @sql
    END

VIEWの作成時にエラーが発生する

「アクティブ」付近の構文が正しくありません。

4
sharad

私たちの会社では、私たちが行うすべてのバージョン管理を強制しているので、個人的にはこのようにしない方がいいです。したがって、オブジェクトが存在するかどうかを確認し、オブジェクトを明示的に作成または変更するスクリプトを作成する必要があります。

つまり、この方法で行う必要がある場合は、バッチ内で単独で実行する必要があるオブジェクトタイプごとに、個別のコマンドを実行してそれらを変更/作成する必要があります。例えば:

IF OBJECT_ID(N'dbo.my_proc',N'P') IS NULL
EXECUTE ('CREATE PROCEDURE [dbo].[my_proc] AS SELECT 1');
EXECUTE ('GRANT EXEC ON [dbo].[my_proc] TO [some_user]');
ELSE
EXECUTE ('ALTER PROCEDURE [dbo].[my_proc] AS SELECT 2');
GO

[〜#〜]編集[〜#〜]

追加情報に基づいて、Maxのソリューションが問題を解決します。ただし、彼が述べたように、SQLエラーを解決するのではなく、正確に引用符を付けていることを確認するためにより多くの時間を費やすので、これは非常に悪い方法です。

それを行うためのより良い方法、そして私が最初に指摘していたことは、次のように各コンポーネントを個別のステートメントに分離することです:

IF DB_ID(N'some_db') IS NOT NULL
BEGIN
PRINT 'EXISTS';
END
ELSE
BEGIN
IF OBJECT_ID(N'dbo.my_table',N'U') IS NULL
BEGIN
EXECUTE(
'CREATE TABLE [dbo].[my_table](
 [id] INT IDENTITY NOT NULL, 
 [name] NVARCHAR(8) NOT NULL,
 CONSTRAINT [pk_my_table] PRIMARY KEY([id]),
 CONSTRAINT [uk_my_table_name] UNIQUE([name])
 )');
END
IF OBJECT_ID(N'dbo.my_view',N'V')IS NULL
BEGIN
EXECUTE(
'CREATE VIEW [dbo].[my_view]
 AS
 SELECT [id],[name]
 FROM [dbo].[my_table]
 WHERE [name] LIKE ''A%'';'
);
END
IF OBJECT_ID(N'dbo.my_proc',N'P') IS NULL
BEGIN
EXECUTE(
'CREATE PROCEDURE [dbo].[my_proc](@id INT)
 AS
 SELECT [name]
 FROM [dbo].[my_view]
 WHERE [id] = @id;'
);
END
END
GO
5
Mr.Brownstone

ブラウンストーンさんが正解です。質問に正解をマークしていただければ幸いです。

さらに助けが必要かもしれないと言った;だからここに行く以下のサンプルは、nvarchar(max)変数を使用して、ストアドプロシージャが存在しない場合に、ストアドプロシージャの作成に使用される埋め込みnvarchar(max)を含むコマンドを実行します。このクラスのコードをデバッグすることはほとんど不可能であるため、これは実行すべきでないことの例です。

USE Master;
GO
IF EXISTS (select name from sys.databases WHERE name = 'Test')
    PRINT 'Test database already exists, doing nothing';
ELSE
BEGIN
    DECLARE @cmd as NVARCHAR(max);
    SET @cmd = '
    CREATE DATABASE Test;   /* CREATE A TEST DATABASE */
    GO
    USE Test;   /* make the Test database active */
    GO
    /* if proc MakeIt exists, then drop the procedure (USE WITH CAUTION!) */
    IF EXISTS (SELECT name FROM sys.procedures WHERE name = ''MakeIt'')
    BEGIN
        DROP PROCEDURE MakeIt;
    END
    GO

    /* create a procedure to make the necessary tables and procedures 
        for this database */
    CREATE PROCEDURE MakeIt
    AS
    BEGIN
        DECLARE @cmd NVARCHAR(max);
        SET @cmd = '''';
        /* if TestTable does not exist, create it. */
        IF NOT EXISTS (SELECT name FROM sys.tables WHERE name = ''TestTable'')
        BEGIN
            CREATE TABLE TestTable
            (
                TestTableID INT NOT NULL CONSTRAINT PK_TestTable 
                    PRIMARY KEY CLUSTERED IDENTITY(1,1)
                , SomeData uniqueidentifier CONSTRAINT DF_TestTable_SomeData
                     DEFAULT (NEWID())
            );
        END

        /* if SomeProc does not exist, create it */
        IF NOT EXISTS (SELECT ''SomeProc'' FROM sys.procedures WHERE name = ''SomeProc'')
        BEGIN
            SET @cmd = 
                ''
                    CREATE PROCEDURE SomeProc
                        @someParam uniqueidentifier
                    AS
                    BEGIN
                        IF NOT EXISTS
                        (
                            SELECT TestTableID 
                            FROM TestTable 
                            WHERE SomeData = @someParam
                        )
                        BEGIN
                            INSERT INTO TestTable (SomeData) VALUES (@someParam);
                        END
                    END
                '';
            /* use sp_executesql to create the procedure in its own batch, 
                negating the need for the ''GO'' statement */
            EXEC sp_executesql @cmd;
        END

    END
    ';
    EXEC sp_executesql @cmd;
END

USE Test;
GO
/* Run the procedure to create the table and stored proc */
EXEC MakeIt;

/* run the stored proc */
DECLARE @ID uniqueidentifier;
SET @ID = NEWID();
EXEC SomeProc @ID;

/* see the result */
SELECT * FROM TestTable;

TestデータベースにDDLデータベーストリガーがある場合、設計の変更を追跡できます。例に似たコードによってデータベースに加えられた変更も追跡できます。これを行う方法に関する私の答えをここで参照してください: SSMS 2005または2008でストアドプロシージャを変更または変更したのは誰ですか?

3
Max Vernon

あなたはすでに文字列の中にいるので、もう一度一重引用符をエスケープする必要があります:

CASE UserStatus WHEN 1 THEN ''''Active'''' WHEN 0 THEN ''''InActive'''' END AS UserStatus

私は個人的にこれらすべてのsp_addextendedpropertyプロシージャを破棄します。他の回答で指摘されているように、独自の変更スクリプトを作成することを検討する必要があります。また、SQL Serverでは GOはステートメントではありません です。

2
bojan