2014-04-07 4 views
0

"Select Max (ID) ...."쿼리로 신청자 등록 ID가 생성되는 신청자 등록 양식을 만듭니다. 이 쿼리가 데이터베이스에서 MaxID를 가져 오면이 ID를 +1 (+1)하여이 ID를 증가시킵니다. 이렇게하면 자신을 등록한 모든 신청자의 등록 ID가 생성됩니다. 그러나 하나의 문제가 서버 및 여러 클라이언트 (약 10)에서 프로젝트를 실행할 때 발생합니다. 신청자가 "기본 키 위반 예외"가 발생하면 등록을 시도합니다. 5 삽입 쿼리가 최대 쿼리 후 하나씩 실행이됩니다데이터베이스에서 고유 한 최대 ID를 생성하는 방법

을 실행

코드가

public long getUid() 
    { 
     try 
     { 
      string qry = "select isnull(max(Temp_Applicant_RegNo),0) as appregno FROM Temp_Reg"; 
      if (cs.State == ConnectionState.Closed) 
      { 
       cs.Open(); 
      } 
      cmd = new SqlCommand(qry, cs); 
      dr = cmd.ExecuteReader(); 
      long cid = 0; 
      if (dr.Read()) 
      { 
       cid = long.Parse(dr["appregno"].ToString()); 
       cid++; 
      } 
      if (cs.State == ConnectionState.Open) 
      { 
       cs.Close(); 
      } 
      return cid; 
     } 
     catch (Exception ex) 
     { 
      lbl_ErrorMsg.Text = ex.Message; 
      return 0; 
     } 
    } 



protected void Save_btn_Click(object sender, EventArgs e) 
    { 
     SqlTransaction trn = null; 
     try 
     { 
      long Regid = getUid();  
      con.Open(); 
      trn = con.BeginTransaction(); 

      cmd = new SqlCommand("insert into....", con, trn); 
      cmd.Parameters.AddWithValue("@RegNo", Regid); 
      cmd.ExecuteNonQuery(); 

      cmd = new SqlCommand("insert into....", con, trn); 
      cmd.Parameters.AddWithValue("@RegNo", Regid); 
      cmd.ExecuteNonQuery(); 

      cmd = new SqlCommand("insert into....", con, trn); 
      cmd.Parameters.AddWithValue("@RegNo", Regid); 
      cmd.ExecuteNonQuery(); 

      trn.Commit(); 
     } 
     catch (Exception ex) 
     { 
      lbl_ErrorMsg.Text = ex.Message; 
      trn.Rollback(); 
     } 
}     

아래와 같습니다 아무런이되도록 어떻게 신청자에 대한 최대 ID를 생성 할 수 없음을 나에게 제안을주십시오 모든 복제 기회. 왜냐하면 나는 라이브 프로젝트에서 일하고 있기 때문이다.

거기에 대해 내가 그렇게하지 마십시오 Asp.net C#을

+0

MAX (ID)를 선택한 다음 증가시키지 마십시오. 기본 키에 IDENTITY를 사용하면 데이터베이스에서 키를 생성합니다. – David

+0

또 다른 옵션은 SQL Server 2012/2014를 사용하는 경우 SEQUENCE를 사용하는 것입니다. –

+0

또는 GUID를 사용하십시오. – Arman

답변

1

을 사용하고, 새 행을 삽입 할 때 데이터베이스가 당신을위한 키를 생성 할 수 있습니다. 예를 들어 SQL Server 또는 MySQL을 사용하는 방법을 예로들 수 있습니다. 클라이언트에서 실제로 수행하려면 GUID를 키로 사용하십시오. 데이터베이스를 참조하지 않고 GUID를 생성 할 수 있기 때문입니다. GUID는 키로 일부 사소한 문제가 있습니다. 일반적으로 부분적으로 무작위이므로 클러스터 된 인덱스에 부정적인 성능 영향을 줄 수 있지만 모든 데이터베이스의 99.9 %는 정상입니다.

0
  1. 해결 방법 1 :

당신은 예를 들어, 하나의 칼럼에 "GeneralID을"테이블을 만들 수 있으며, 응용 프로그램 제어에이 ID를 다른 테이블에 삽입 할 수 있습니다.

  1. 해결 방법 2 :

또 다른 해결책은 삽입 "IDS 테이블"frmo 점점 ID를 popule에 삽입하기 전에 각 테이블에 테이블과 하나의 열 및 트리거를 만드는 것입니다.

0

자동 증가 열이 있기 전에는 ID를 보유 할 테이블이 있습니다. IdType varchar (10) 및 NextId int 열이 2 개만 있습니다. 저장된 프로 시저에서 다음과 같은 것을 얻을 수 있습니다 :

while(1=1) 
begin 
    select @nextId = nextId 
    from MyIds 
    where [email protected] 

    update MyIds 
    set nextId = @nextId + 1 
    where [email protected] 
    and nextId = @nextId 

    if(@@ROWCOUNT > 0) 
     break; 
end 

select @nextId as nextId 

nextId가 변경되지 않은 경우에만 두 번째 명령문에서 업데이트됩니다. 변경된 경우 다시 시도합니다.

0

당신이 Temp_Reg에 새 값을 저장 할 때이 있지만 계산 후 즉시 그 값을 저장하면, 다음 업데이트 다른 테이블 안전에 할 수있는 방법을 참조하지 않습니다

public long getUid() 
{ 
    try 
    { 
     string qry = "select isnull(max(Temp_Applicant_RegNo),0) as appregno FROM Temp_Reg"; 
     if (cs.State == ConnectionState.Closed) 
     { 
      cs.Open(); 
     } 
     cmd = new SqlCommand(qry, cs); 
     dr = cmd.ExecuteReader(); 
     long cid = 0; 
     if (dr.Read()) 
     { 
      cid = long.Parse(dr["appregno"].ToString()); 
      cid++; 
     } 

UPDATE Temp_reg HERE !!!! 

     if (cs.State == ConnectionState.Open) 
     { 
      cs.Close(); 
     } 
     return cid; 
    } 
    catch (Exception ex) 
    { 
     lbl_ErrorMsg.Text = ex.Message; 
     return 0; 
    } 
} 

그럼 당신은해야합니다을 Save_btn_Click의 catch 블록 내에서이 업데이트를 고려해야합니다.

자동 넘버를 사용할 수 없다면이 모든 것이 가능하지만 가능한 경우 사용하십시오.

0

IDENTITY 열에서 Temp_Applicant_RegNo 필드를 변경할 수있는 경우 테이블 Temp_Reg에 할당 된 다음 번호를 염려 할 필요가 없습니다. 그것은 당신의 데이터베이스에 의해 만들어진 모든 jopb입니다.
알아야 할 것은 번호가 할당 된 번호이며 다음 번 삽입시 해당 번호를 사용하십시오.
이것은 쉽게

protected void Save_btn_Click(object sender, EventArgs e) 
{ 
    SqlTransaction trn = null; 
    try 
    { 
     con.Open(); 
     trn = con.BeginTransaction(); 

     cmd = new SqlCommand("insert into....; SELECT SCOPE_IDENTITY()", con, trn); 
     int Regid = Convert.ToInt32(cmd.ExecuteScalar()); 

     cmd = new SqlCommand("insert into....", con, trn); 
     cmd.Parameters.AddWithValue("@RegNo", Regid); 
     cmd.ExecuteNonQuery(); 

     cmd = new SqlCommand("insert into....", con, trn); 
     cmd.Parameters.AddWithValue("@RegNo", Regid); 
     cmd.ExecuteNonQuery(); 

     trn.Commit(); 
    } 
    catch (Exception ex) 
    { 
     lbl_ErrorMsg.Text = ex.Message; 
     trn.Rollback(); 
    } 

트릭에 삽입 후 SELECT SCOPE_IDENTITY()을 사용하여 수행 할 수있는 것은 처음 삽입 할 두 번째 쿼리로 SELECT SCOPE_IDENTITY()를 추가 할 수 있습니다 다음 ExecuteScalar는 전화. ExecuteScalar는 쿼리를 실행 한 다음 실행 된 마지막 쿼리의 첫 번째 행에있는 첫 번째 열의 값을 반환합니다.

+0

좋아, 나는 그것을 시도 할 것이다. 그러나 여러 클라이언트가 동시에 상호 작용할 때 어떤 일이 발생합니까? 둘 이상의 사용자가 동시에 상호 작용할 경우 SCOPE_IDENTITY()는 마지막으로 실행 된 쿼리의 값을 모든 클라이언트에 반환합니다. –

관련 문제