2008-10-09 6 views
13

데이터베이스에서 INSERT 문을 실행하고 Auto_Increment 기본 키를 반환하는 함수가 필요합니다. 나는 다음과 같은 C# 코드를 가지고 있지만 INSERT 문은 잘 작동하지만 (데이터베이스의 레코드를 볼 수 있으며 PK는 올바르게 생성되고 행 == 1), id 값은 항상 0입니다. 잘못된? 답변에 대한 응답으로INSERT 문 다음에 오는 @@ IDENTITY는 항상 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; 
    } 

하지만 지금 내가 MS 액세스를 사용하고

"SQL 문 종료 후 발견 문자"오류를 받고 있어요 OleDb 연결을 사용하는 데이터베이스, Provider = Microsoft.Jet.OLEDB.4.0

+0

당신이 사용중인 데이터베이스 서버 명확히 가능성이 InitializeAndOpenConnection/connection.CreateCommand에 대한 참조를 인라인 수를 당신? :) – Rob

+0

또한 OID = SCOPE_IDENTITY() 인 "OID FROM x OID = SCOPE_IDENTITY()"의 전체 내용은 ID 값 3으로 삽입 된 레코드의 경우 다소 복잡합니다. "SELECT 3 FROM table_x WHERE 3 = 3 "- 다소 중복 됨 – Rob

+0

@Rob : 중복 된 것처럼 보일 수 있지만 OID는 scope_identity()가 아닌 int 유형이므로 cmd.ExecuteScalar()를 직접 캐스팅 할 수 있습니다. – devio

답변

1

첫 번째 create 명령에 Select @@ ID가 있어야한다고 생각합니다. "; @@ Identity"및 .ExecuteScalar를 통해 추가하십시오.삽입문

0

테이블에 다른 테이블에 삽입 할 수있는 트리거가 있습니까? 일반적으로 우리는 @@ Identity에 IDENT_CURRENT을 사용하는 것에 반대하여 반환 된 ID가 방금 삽입 한 테이블에 대한 것임을 보증 할 수 있습니다.

+1

SCOPE_IDENTITY는 현재 세션 및 현재 범위에있는 테이블에 대해 생성 된 마지막 ID 값을 반환하므로 SCOPE_IDENTITY를 사용해야한다고 생각합니다. 따라서 테이블에 삽입 한 후에 호출하면 적절한 값을 얻을 수 있습니다. – kristof

+0

IDENT_CURRENT를 사용하여 테이블 이름을 지정하더라도 조작 범위 내에 있음을 보장하지는 않습니다. 정의 : "지정된 테이블 또는 뷰에 대해 생성 된 마지막 ID 값을 리턴합니다. 생성 된 마지막 ID 값은 모든 세션 그리고 어떤 범위든지 " – kristof

+0

나는 어느 쪽이든에는 그것의 결점이 그때다는 것을 생각한다. 동일한 테이블에서 "다른"ID를 가져 오는 기회는 동일한 범위의 다른 테이블에서 ID를 얻는 것과 유사합니다. @@ Identity보다 낫다. –

0

나는 @@ identity가 명령의 범위에서만 유효하다고 생각합니다. - 당신이 "statement"를 실행할 때.

저장 프로 시저 자체가 @@ IDENTITY 값을 INSERT 문 다음에 반환하고 저장 프로 시저 실행의 반환 코드로 읽도록 "문"을 수정하십시오. ";"

15

1) (사용하여 연결하여 삽입 및 SELECT 문을 결합 1dB 명령으로)

2) 대신 @@ IDENTITY blabla INTO

INSERT ...의) SCOPE_IDENTITY를 (사용; 테이블에서 SELECT OID WHERE OID = SCOPE_IDENTITY()

- 업데이트 :이 문제는 MS ACCESS에 관련이 있음을 알고 보니, 나는 단순히 첫 번째 명령을 재사용하고있는 CommandText를 설정하는 것을 제안 this article을 발견

"SELECT @@ IDENTITY"로 충분해야합니다.

+0

그 이유는 그렇지 않으면 두 명령을 실행하고 두 번째 명령은 첫 번째 명령에 대해 zilch를 알고 있으므로 IDENTITY 값을 작성한 후에는 두 번째 (연결이 끊어진) 명령에서 가져 오지 못하기 때문입니다. –

+0

이렇게하면 "SQL 문 끝에서 발견 된 문자"오류 – Gillian

+0

은 첫 번째 문 다음에 "SELECT SCOPE_IDENTITY()"를 사용합니다. 이에 대한 좋은 설명은 아래 링크를 참조하십시오. – evilhomer

-1

Access를 사용하는 경우 aspfaq에서 this article을 살펴본 다음 페이지의 절반 정도 아래로 스크롤하십시오. 이 코드는 기존 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'를 추가하는 연결을 정돈 할 필요가 있습니다.

4

초기 연결을 열 때와 동시에 ID를 반환해야합니다. 삽입 또는 출력 변수에서 결과 세트를 리턴하십시오.

@@ identity가 아닌 SCOPE_IDENTITY()도 항상 사용해야합니다.Reference here

당신은 삽입 후

SELECT SCOPE_IDENTITY() 

을 추가해야합니다.

+2

-1 Access 데이터베이스에 없습니다. – Fionnuala

0

데이터베이스 설정을 확인하십시오. 나는 전에 비슷한 문제가 있었으며 SQL Server 연결 설정 'no count'가 활성화되었음을 발견했습니다.

SQL Server Management Studio에서는 개체 탐색기에서 서버를 마우스 오른쪽 단추로 클릭하고 속성을 선택한 다음 연결 페이지로 이동합니다. "기본 연결 옵션"의 설정 살펴보기

+0

Doh, 그냥 SQL Server가 아닌 MS Access를 사용하고 있다는 것을 읽으십시오. 내 대답이 MS Access에 적용되는지 확실하지 않습니다 ... –

+0

Access가 아니라 Jet를 사용하고 있습니다. –

4

Jet는 SQL Server가 아니며 Jet는 명령별로 하나의 SQL 문만 처리 할 수 ​​있으므로 별도의 명령으로 SELECT @@IDENTITY을 실행해야합니다. INSERT과 동일한 연결입니다.

0

대부분의 응답자가 Asker가 SQL Server를 사용하고 있지 않다는 사실을 잊지 않았습니까?

명백하게 MS Access 2000 이상 doesn't support @@IDENTITY. 대체 방법은 "RowUpdated 이벤트를 사용하면 INSERT가 발생했는지 확인하고 최신 @@ IDENTITY 값을 검색 한 다음이를 DataSet의 로컬 테이블에있는 ID 열에 배치 할 수 있습니다."

예, 이것은 Access DB에 포함 된 VBA 용입니다. 여전히 Access Object Library를 통해 Access 외부에서 호출 할 수 있습니다.

편집 : ok, 지원됩니다. 조급 한 이른 아침 답변에 사과드립니다. 그러나이 답변의 나머지 부분이 도움이 될 수 있습니다.

+0

"MS Access 2000 이상은 @@ IDENTITY를 지원하지 않습니다."- 잘못된 길을 찾아 왔습니다. @@ IDENTITY는 MS Access 2000 이상에서만 지원됩니다. OP는 MS Access 2000과 함께 처음 출시 된 Jet 4.0을 사용하고 있다고 대답했습니다. – onedaywhen

+0

대부분의 응답자는 잊지 않고 있습니다. 대상 데이터베이스 엔진이 Access라는 사실은 몇 가지 해답이 제시 될 때까지 명시되지 않았습니다. – Rob

+0

이야기의 도덕 : 오전 6시에 질문에 대답하지 마십시오. – moffdub

7

Microsoft.Jet.OLEDB.4.0 공급자는 Jet v3 및 Jet v4 데이터베이스 엔진을 지원하지만 SELECT @@ IDENTITY는 Jet v3에서 지원되지 않습니다.

MSAccess 97은 Jet v3이며 SELECT @@ IDENTITY를 지원하지 않습니다. MSAccess 2000 이상을 지원합니다.

+0

동일한 문제가 발생한 후에도 동일한 결론에 도달했습니다. 다른 대답의 다른 모든 "솔루션"은 Access/Jet에만 적용되지 않습니다. –

0

삽입하려는 트랜잭션의 자동 실행 수와 검색 환경의 값을 검색하려면 을 입력하십시오. 1. 데이터베이스는 MsAccess입니다. 2. 드라이버는 다음과 같이 연결 문자열로 Jet4이다 "공급자 = Microsoft.Jet.OLEDB.4.0; 암호 = {0}; 데이터 소스 = {1}; 지속 보안 정보 = True"로 3. 사용 OLEDB


1. 두 명령 단일 쿼리를 수용 각을 만들기 : 당신은 당신의 코드에

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

-1 데이터베이스는 Jet/ACE입니다. – Fionnuala

0

짧은 대답을 내 예를 적용 할 수 있습니다.
2. 첫 번째 SQL 쿼리는 INSERT 레코드입니다.
3. 두 번째 sql 쿼리는 "SELECT @@ Identity;"입니다. 일련 번호를 반환합니다.
4. 첫 번째 행의 첫 번째 열을 반환하는 cmd.ExecuteScalar()를 사용하십시오.
5. 반환 된 결과 출력은 현재 삽입 쿼리에서 생성 된 일련 번호 값입니다.

It is referenced from this link. 예제 코드는 아래와 같습니다. "SAME 연결 VS 새 연결"의 차이점에 유의하십시오. SAME 연결은 원하는 출력을 제공합니다.

class Program 
{ 
    static string path = @"<your path>"; 
    static string db = @"Test.mdb"; 
    static void Main(string[] args) 
    { 
     string cs = String.Format(@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0}\{1}", path, db); 
     // Using the same connection for the insert and the SELECT @@IDENTITY 
     using (OleDbConnection con = new OleDbConnection(cs)) 
     { 
      con.Open(); 
      OleDbCommand cmd = con.CreateCommand(); 
      for (int i = 0; i < 3; i++) 
      { 
       cmd.CommandText = "INSERT INTO TestTable(OurTxt) VALUES ('" + i.ToString() + "')"; 
       cmd.ExecuteNonQuery(); 

       cmd.CommandText = "SELECT @@IDENTITY"; 
       Console.WriteLine("AutoNumber: {0}", (int)cmd.ExecuteScalar()); 
      } 
      con.Close(); 
     } 
     // Using a new connection and then SELECT @@IDENTITY 
     using (OleDbConnection con = new OleDbConnection(cs)) 
     { 
      con.Open(); 
      OleDbCommand cmd = con.CreateCommand(); 
      cmd.CommandText = "SELECT @@IDENTITY"; 
      Console.WriteLine("\nNew connection, AutoNumber: {0}", (int)cmd.ExecuteScalar()); 
      con.Close(); 
     } 
    } 
} 

이 자기 설명 출력을 생성한다 : 그들은 우리의 응답에 영향을 미칠 수 있으므로

AutoNumber: 1 <br> 
AutoNumber: 2 <br> 
AutoNumber: 3 <br> 

New connection, AutoNumber: 0 
관련 문제