0

最初に、データベース スキーマをまったく変更できないと言わせてください。

データベースと対話する既存のコードにはアクセスできません。コンパイル済みのアセンブリであり、逆コンパイルできません。

ここに画像の説明を入力

コード内で論理的に主キーとして機能するが、自動インクリメントされない値を持つデータベース テーブルがあります。

ここでねじれがあります。キーが正の数を増やしたり、負の数を増やしたりすることがあります。:(

hilo コードの証拠が見つかりません。

SELECT TOP 1 を実行して値を追加する以外に、これに対処する方法がわかりません。重複が発生しないことを願っています。

4

3 に答える 3

0

Steve のソリューションは非常に優れており、特にデータベース コンテナとルールの割り当てを利用していますが、明らかに (ある程度) 状況に行き詰まっています。レコードを追加しようとしていて、独自の自動インクリメントを作成する必要がある場合は、プロシージャ コールだけでそれを実行して割り当てる必要がある場合があります。これはほんの一例ですが、参考になるかもしれません。

FUNCTION AddMyNewRecord()
   */ localized variable so you don't accidentally mangle some otherwise 
   */ coincidental variable somewhere else.  Preserve work area at start
   local lnSelect, llSaveOk, lnAttempts, lnNewPKID
   lnSelect = select()
   llSaveOk = .f.    

   select YourAddressTable
   if NOT FLOCK()
      lnAttempts = 0
      do while lnAttempts < 10 AND NOT FLOCK()
         wait window "Attempting lock for address table..." timeout 1
      enddo
   endif 

   if NOT FLOCK()
      messagebox( "Unable to lock file to add next record primary key." )
   else
      */ We have a lock, now try to detect both the highest and lowest
      */ EXISTING key for the table
      use in select( "C_TryNextKey" )
      select MIN( YAT.PK ) as MinKey,;
             MAX( YAT.PK ) as MaxKey ;
         from ;
            YourAddressTable YAT;
         into ;
            cursor C_TryNextKey readwrite 

      */ Determine if you need higher or lower key sequence
      if CriteriaForPositiveKey
         lnNewPKID = C_TryNextKey.MaxKey +1
      else
         */ must be getting next LOWER sequence
         lnNewPKID = C_TryNextKey.MinKey -1
      endif 

      */ close temp cursor from getting respective high / low key
      use in select( "C_TryNextKey" )

      */ NOW, we can add the new record
      Select YourAddressTable
      APPEND BLANK
      */ replace PK and all the other fields you need to do too
      Replace PK with lnNewPKID,;
              Address1 with lcSomeVariableYouHaveForAddress1,;
              Address2 with lcSomeVariableForAddress2,;
              AnyOtherFields with lcOtherFieldsToBeSet

      */ Unlock the address table
      UNLOCK

      */ set flag so we know it worked vs not.
      llSaveOk = .t.
   endif  

   */ Return back where it started
   select( lnSelect )

   */ Return if the save was ok or not.
   return llSaveOk
endproc 

これにより、既存のデータベースもテーブル構造も変更されません。ただし、新しいレコード コンテンツを挿入する前に、テーブルをロックしようとします。次に、最小 ID と最大 ID を確認します。データを分析して、一部が負と正である理由を見つけ、上記のコードに入れられた「プレースホルダー」の条件を更新する必要があります。最後に、テーブルのロックを解除します。

これが理にかなっている場合は、素晴らしいです。調整が必要な場合は、私に知らせてください。さらにガイドできるようにします.

于 2013-06-19T18:27:57.563 に答える