0

テーブルや列などを作成するためのSQLコマンドがたくさんある大きなSQLテキストファイルがあります。

行の例:

IF NOT EXISTS ( SELECT * FROM dbo.sysobjects WHERE id = object_id(N'xcal_views') AND OBJECTPROPERTY(id, N'IsUserTable') = 1) 
   CREATE TABLE xcal_views (lid INT NOT NULL);
GO

IF NOT EXISTS ( SELECT * FROM dbo.sysobjects WHERE id = object_id(N'xcal_views_actors') AND OBJECTPROPERTY(id, N'IsUserTable') = 1) 
   CREATE TABLE xcal_views_actors (lid INT NOT NULL);
GO

IF NOT EXISTS ( SELECT * FROM dbo.syscolumns, dbo.sysobjects WHERE [dbo].[syscolumns].[name] = 'xlactor' AND [dbo].[sysobjects].[id] = [dbo].[syscolumns].[id] AND [dbo].[sysobjects].[id] = object_id(N'xcal_views_actors') AND OBJECTPROPERTY([dbo].[sysobjects].[id], N'IsUserTable') = 1 ) 
   ALTER TABLE [dbo].[xcal_views_actors] ADD xlactor INT NULL;
GO

IF NOT EXISTS ( SELECT * FROM dbo.syscolumns, dbo.sysobjects WHERE [dbo].[syscolumns].[name] = 'lparentid' AND [dbo].[sysobjects].[id] = [dbo].[syscolumns].[id] AND [dbo].[sysobjects].[id] = object_id(N'xcal_views_actors') AND OBJECTPROPERTY([dbo].[sysobjects].[id], N'IsUserTable') = 1 ) 
   ALTER TABLE [dbo].[xcal_views_actors] ADD lparentid INT NULL;
GO

IF NOT EXISTS ( SELECT * FROM dbo.sysobjects WHERE parent_obj = (SELECT id FROM dbo.sysobjects WHERE id = object_id(N'xcal_views_actors') AND OBJECTPROPERTY(id, N'IsUserTable') = 1) AND OBJECTPROPERTY(id, N'IsPrimaryKey') = 1) 
   ALTER TABLE [dbo].[xcal_views_actors] 
   ADD CONSTRAINT [CT_00000501] PRIMARY KEY CLUSTERED (lid ASC);
GO

IF NOT EXISTS ( SELECT * FROM [sys].[indexes] i INNER JOIN [sys].[objects] o ON o.object_id = i.object_id AND o.name = 'xcal_views_actors' WHERE i.name = 'parent_id' ) 
   CREATE INDEX parent_id ON xcal_views_actors (lparentid ASC)
GO

各コマンドの間に、コマンドGOを区切るための余分な行があります。

patch.sqlSQL Server Management Studioからファイル全体を実行すると、すべてのコマンドが実行され、正常に機能します。

.NETでは、テキストファイル全体を読み取り、「GO」で分割して、データベースに対して各SQLコマンドを実行します。

奇妙なことに、一部のコマンドは実行されません。そして、その理由がわかりません。

これは仕事をする方法です:

private static void patchDatabase(string connection, string sqlfile)
{
  var defaultEncoding = Encoding.Default;
  using (FileStream fs = File.OpenRead(sqlfile))
  {
    defaultEncoding = TextFileEncodingDetector.DetectTextFileEncoding(fs, defaultEncoding, 1024);
  }
  //Console.WriteLine(string.Format("File {0} using encoding: {1}",sqlfile, defaultEncoding));

  var dbPatch = new StreamReader(sqlfile, defaultEncoding);
  string sqlPatch = dbPatch.ReadToEnd();
  dbPatch.Close();
  string[] stringSeparators = new[] {"GO"};
  string[] sqlPatches = sqlPatch.Split(stringSeparators, StringSplitOptions.None);

  if (connection != null && sqlPatch.Length > 0)
  {
    Console.WriteLine(string.Format("Executing {0} statements from {1}", sqlPatches.Length, sqlfile));

    using (var cnn = new SqlConnection(connection))
    {
      cnn.Open();
      foreach (var sql in sqlPatches)
      {
        if (String.IsNullOrEmpty(sql))
          continue; // Not a real sql statement, use next

        using (var cmd = new SqlCommand(sql, cnn))
        {
          try
          {
            cmd.CommandTimeout = 120;
            cmd.ExecuteNonQuery();
            //int results = cmd.ExecuteNonQuery();
            //if (results < 1)
            //  Console.WriteLine(String.Format("Failed:\nResult: {0}\n{1}",results, sql));
          }
          catch (Exception ex)
          {
            Console.WriteLine("Execution error!\n\n" + sql + "\n\n\n" + ex);
          }
        }
      }
      cnn.Close();
    }

  }
}

関数が飛び散ったようです...

現在のテキストファイルには約6.000行以上あります。

私が何を間違えているのか分かりますか?

4

1 に答える 1

0

コーディングの問題ではなかったようです。

実際、私は次の状況を作り出しました。

  • 私はデータベース「test_db」を持っています

  • 私はユーザー「test_db_user」を作成し、彼をdb_ownerにします。彼は一般に「security--roles」に追加されます。objekt「test_db」はロールdb_ownerとして追加されます。彼はデータベース「test_db」--security--userにもユーザーとして追加されます。

  • 今、それは来ます:私はいくつかのテストの後にデータベースを再び復元しました。ユーザーは「test_db」--security--userにリストされなくなりましたが、一般にdb_ownerとして構成されています。

どういうわけか接続は機能しますが、常にデータベースに完全にアクセスできるわけではありません。何が悪いのか本当にわかりません。管理スタジオから、SQLバッチを開始するために管理者アカウントを使用したことがあります。これが、SQLバッチが常に機能する理由です。

だから解決策:セキュリティ設定が100%正しいことを確認してください:S

もう一つの問題は私の愚かさでした:S !!! dboなしでいくつかのcreatetableステートメントがありました。テーブルの前にスキーマがあるため、別のユーザーがテーブルに別のスキーマ名を作成しました。

フィードバックをありがとうございました。

于 2012-05-25T18:51:10.537 に答える