14

データベースで INSERT ステートメントを実行し、Auto_Increment 主キーを返す関数が必要です。私は次の C# コードを持っていますが、INSERT ステートメントは正常に動作しますが (データベース内のレコードを確認でき、PK は正しく生成され、行 == 1)、id 値は常に 0 です。違う?

    public int ExecuteInsertStatement(string statement)
    {
        InitializeAndOpenConnection();
        int id = -1;


        IDbCommand cmdInsert = connection.CreateCommand();
        cmdInsert.CommandText = statement;
        int rows = cmdInsert.ExecuteNonQuery();

        if (rows == 1)
        {
            IDbCommand cmdId = connection.CreateCommand();
            cmdId.CommandText = "SELECT @@Identity;";
            id = (int)cmdId.ExecuteScalar();
        }

        return id;
    }
    private void InitializeAndOpenConnection()
    {
        if (connection == null)
            connection = OleDbProviderFactory.Instance.CreateConnection(connectString);

        if(connection.State != ConnectionState.Open)                 
            connection.Open();
    }

答えに応じて、私は試しました:

public int ExecuteInsertStatement(string statement, string tableName)
    {
        InitializeAndOpenConnection();
        int id = -1;
        IDbCommand cmdInsert = connection.CreateCommand();
        cmdInsert.CommandText = statement + ";SELECT OID FROM " + tableName + " WHERE OID = SCOPE_IDENTITY();";
        id = (int)cmdInsert.ExecuteScalar();

        return id;
    }

しかし、「SQLステートメントの終了後に文字が見つかりました」というエラーが表示されます

OleDb 接続で MS Access データベースを使用しています。Provider=Microsoft.Jet.OLEDB.4.0

4

13 に答える 13

15

1) INSERT ステートメントと SELECT ステートメント (「;」を使用して連結) を 1 つの db コマンドに結合します。

2) @@IDENTITY の代わりに SCOPE_IDENTITY() を使用する

ブラブラに挿入... ; SELECT OID FROM table WHERE OID = SCOPE_IDENTITY()

- アップデート:

質問がMS ACCESSに関連していることが判明したため、最初のコマンドを再利用し、そのCommandTextを「SELECT @@IDENTITY」に設定するだけで十分であることを示唆するこの記事を見つけました。

于 2008-10-09T09:42:35.170 に答える
7

Microsoft.Jet.OLEDB.4.0プロバイダーはJetv3およびJetv4データベースエンジンをサポートしていますが、SELECT@@IDENTITYはJetv3ではサポートされていません。

MSAccess97はJetv3であり、SELECT@@IDENTITYをサポートしていません。MSAccess2000以降でサポートされています。

于 2008-10-09T12:13:57.687 に答える
4

最初の接続を開くと同時に ID を返す必要があります。挿入または出力変数から結果セットを返します。

また、@@identity ではなく、常に SCOPE_IDENTITY() を使用する必要があります。ここを参照

追加する必要があります

SELECT SCOPE_IDENTITY() 

挿入後。

于 2008-10-09T09:42:50.567 に答える
4

Jet (SQL Server ではない) を使用しており、Jet はコマンドごとに 1 つの SQL ステートメントしか処理できないためSELECT @@IDENTITY、別のコマンドで実行する必要がありますINSERT

于 2008-10-09T10:22:45.523 に答える
1

最初の作成コマンドで @@identity を選択する必要があると思います - ";SELECT @@Identity" と .ExecuteScalar 挿入ステートメントを介して追加してみてください

于 2008-10-09T09:40:54.797 に答える
0

挿入しているトランザクションの自動実行番号の値を取得したい場合、および環境は次の 1. データベースは MsAccess です。2. ドライバーは、"Provider=Microsoft.Jet.OLEDB.4.0;Password={0};Data Source={1};Persist Security Info=True" のような接続文字列を持つ Jet4 です。 3. Oledb を使用します。

私の例をコードに適用できます

OleDbConnection connection =  String.Format("Provider=Microsoft.Jet.OLEDB.4.0;Password={0};Data Source={1};Persist Security Info=True",dbinfo.Password,dbinfo.MsAccessDBFile);
connection.Open();
OleDbTransaction transaction = null;
try{
    connection.BeginTransaction();
    String commandInsert = "INSERT INTO TB_SAMPLE ([NAME]) VALUES ('MR. DUKE')";
    OleDbCommand cmd = new OleDbCommand(commandInsert , connection, transaction);
    cmd.ExecuteNonQuery();
    String commandIndentity = "SELECT @@IDENTITY";
    cmd = new OleDbCommandcommandIndentity, connection, transaction);
    Console.WriteLine("New Running No = {0}", (int)cmd.ExecuteScalar());
    connection.Commit();
}catch(Exception ex){
    connection.Rollback();
}finally{
    connection.Close();
}   
于 2009-05-22T23:19:27.037 に答える
0

テーブルに、他のテーブルに挿入している可能性のあるトリガーはありますか? 一般に、 IDENT_CURRENTを優先して @@Identity を使用しないことをお勧めします。これにより、返された ID が挿入したばかりのテーブルのものであることを保証できます。

于 2008-10-09T09:41:39.803 に答える
0

@@identity は、コマンドの範囲内でのみ有効だと思います-あなたの場合、「ステートメント」を実行するとき。

ストアド プロシージャ自体が INSERT ステートメントの直後に @@IDENTITY 値を返すように「ステートメント」を変更し、それをストアド プロシージャ実行のリターン コードとして読み取ります。

于 2008-10-09T09:42:24.937 に答える
0

データベースの設定を確認してください。少し前に同様の問題が発生し、SQL Server 接続設定の「カウントなし」が有効になっていることがわかりました。

SQL Server Management Studio では、オブジェクト エクスプローラーでサーバーを右クリックし、[プロパティ] を選択して [接続] ページに移動すると、これを見つけることができます。「デフォルトの接続オプション」の設定を見てください

于 2008-10-09T10:00:25.010 に答える
0

ほとんどの回答者は、質問者が SQL Server を使用していないことを忘れていませんか?

どうやら、MS Access 2000 以降は @@IDENTITY をサポートしていないようです。別の方法としては、「RowUpdated イベントを使用して、INSERT が発生したかどうかを判断し、最新の @@IDENTITY 値を取得して、それを DataSet のローカル テーブルの ID 列に配置できます。」

はい、これは Access DB に埋め込まれた VBA 用です。これは、Access Object Library を介して Access の外部でも呼び出すことができます。

編集:OK、サポートされています。早朝の不機嫌な回答で申し訳ありません。しかし、この答えの残りの部分は役立つかもしれません。

于 2008-10-09T10:51:00.757 に答える
-1

Access を使用している場合は、aspfaq のこの記事を参照し、ページの半分ほど下までスクロールしてください。コードは従来の ASP にありますが、原則はそのまま維持されることを願っています。


SELECT @@Identity は、別の実行コンテキストとして扱われることになると思います。動作するはずのコードは次のとおりです。

public int ExecuteInsertStatement(string statement)
{
    InitializeAndOpenConnection();

    IDbCommand cmdInsert = connection.CreateCommand();
    cmdInsert.CommandText = statement + "; SELECT @@Identity";
    object result = cmdInsert.ExecuteScalar();

    if (object == DBNull.Value)
    {
       return -1;
    }
    else
    {
       return Convert.ToInt32(result);
    }
}

ただし、コードの最後に「SELECT @@Identity」を追加する連結を整理したい/整​​理する必要があるでしょう。

于 2008-10-09T09:42:42.360 に答える
-2
CREATE procedure dbo.sp_whlogin
(
 @id nvarchar(20),
 @ps nvarchar(20),
 @curdate datetime,
 @expdate datetime
)

AS
BEGIN
 DECLARE @role nvarchar(20)
 DECLARE @menu varchar(255)
 DECLARE @loginid int

 SELECT     @role = RoleID
 FROM         dbo.TblUsers
 WHERE    UserID = @id AND UserPass = @ps

 if @role is not null 
 BEGIN
  INSERT INTO TblLoginLog (UserID, LoginAt, ExpireAt, IsLogin) VALUES (@id, @curdate, @expdate, 1);
  SELECT @loginid = @@IDENTITY;
  SELECT @loginid as loginid, RoleName as role, RoleMenu as menu FROM TblUserRoles WHERE RoleName = @role
 END
 else
 BEGIN
  SELECT '' as role, '' as menu
 END
END
GO
于 2010-01-10T08:22:25.980 に答える