2011-08-05 7 views
0

私は、自動増分ID列を持たないデータベース(iSeries)で作業しています。したがって、私はアプリケーションでオンザフライでIDを生成する必要があります。iSeriesテーブルにColdFusionアプリケーション生成ID値を挿入する最も良い方法は何ですか?

私はいくつかのテーブルのために、これらのIDを生成する必要があるため、私は、私のためにこれを実現し、ユーザー定義関数があります。(私はこれは非常に安全ではありません知っているが、これはベアです

<cffunction name="getNewTableId" returntype="numeric" output="false"> 
    <cfargument name="TableName" type="string" required="true" /> 
    <cfargument name="ColumnName" type="string" required="true" /> 
    <cfargument name="SeedNum" type="numeric" required="false" default="1" /> 

    <cfquery name="qMaxId" datasource="#REQUEST.DSN#"> 
     SELECT  MAX(#ARGUMENTS.ColumnName#) AS Id 
     FROM  #ARGUMENTS.TableName# 
    </cfquery> 

    <cfscript> 
     if (qMaxId.RecordCount && IsValid("integer", qMaxId.Id)) 
      return qMaxId.Id + 1; 

     return ARGUMENTS.SeedNum; 
    </cfscript> 
</cffunction> 

骨はちょうどそれが今の彼の開発環境をint作業得るために)

私の質問があり、何のメリット/ローカルID値を保存するとは対照的に、INSERT文の中から関数を呼び出すの欠点:。

  1. ColdFusionのウィリーは、文を準備して実行するので、私は、最初のオプションの方に傾く傾向にあるなステートメント

    <cfset newId = getNewTableId('MyTable','ID') /> 
    
    <cfquery datasource="#REQUEST.DSN#"> 
        INSERT INTO MyTable    
         (
          ID, 
          NameTxt 
         ) 
        SELECT #newId#, 
          <cfqueryparam 
           value="#FORM.MyName#" 
           cfsqltype="CF_SQL_VARCHAR" 
           maxlength="20" /> 
    </cfquery> 
    

を挿入するために前にIDを生成するINSERTなステートメント内

<cfquery datasource="#REQUEST.DSN#"> 
    INSERT INTO MyTable    
     (
      ID, 
      NameTxt 
     ) 
    SELECT #getNewTableId('MyTable','ID')#, 
      <cfqueryparam 
       value="#FORM.MyName#" 
       cfsqltype="CF_SQL_VARCHAR" 
       maxlength="20" /> 
</cfquery> 
  • をIDを生成します値をローカルに格納するのではなく、直ちにColdFusionでSQL文を準備します。

    違いがありますか?

  • +0

    私はほとんど違いが見えません。どちらの場合も、CFは最初に 'getNewTableId'を実行します。その後、 'INSERT'を処理します。しかしどちらのオプションもスレッドセーフではありません。 – Leigh

    +0

    DB2には自動インクリメントがあります。詳細については、@JamesAリンクを参照してください。 – corretge

    +0

    IDAがなぜあなたのために追加できないのか、DBAと話し合う価値があります。私の環境では、RPGとCOBOLプログラムを再コンパイルする必要があるのは、DB表のレイアウトに依存する(レコードを反復し、SQLを使用しないためです)。これを乗り越えるために、別のスキーマを設定してそこにテーブルを再作成しました。スキーマを変更できるようになりましたが、今はそれらをトリガーと結びつけています... http:// stackoverflow。com/questions/7017355/db2-keeping-n-columns-in-two-tables間 – Quaternion

    答えて

    1

    AS/400は、列定義でGENERATED ... AS IDENTITYを使用して、自動インクリメントID列をサポートしています。

    詳細については、SQL Reference: CREATE TABLEステートメントを参照してください。

    +0

    残念ながら、私はデータベース内のIDENTITY列の自動インクリメントを割り当てる機能を持っていません。助けて。しかし、あなたが私の質問に答えるための提案があれば、それは非常に感謝します。 –

    +0

    ご迷惑をおかけして申し訳ございませんが、データベースエンジン自体ではなく、データベーススキーマを参照していたことがわかりました。 – jamesallman

    0

    いずれにしても、重複の可能性があるようです。

    2人のユーザーが同じアクションを同時に実行し、max idを取得するクエリが500ミリ秒(長い時間ですが、目的のために)かかるとすると、必然的に重複したIDが作成されます。 2つのソリューション:

    1. トランザクション内でgetIDクエリとinsertクエリの両方をカプセル化します。
    2. idやdateなど、クラスタ化された主キーを使用してテーブルをやり直します。

    変数としてIDを格納する方が良い場合は、「このIDの後のどの時点でもこのIDを使用しますか?

    +1

    デフォルトのトランザクションレベルは他のスレッドをブロックしません。したがって、 'serializable'トランザクションが必要です。 http://www.garyrgilbert.com/blog/index.cfm/2008/7/15/Cftransaction-Explained(@JamesAが正しい場合、自動的にインクリメントする列は実際にネイティブにサポートされていますが、それが最善の策です)。 ) – Leigh

    +0

    確かに、私はオペアンプがスキーマを修正する能力を持っていたかどうかはわかりませんでした。 –

    +0

    はい、どちらもわかりませんでした。私はちょうど彼が彼のdruthersを持っている場合*は、ネイティブオプションと一緒に行く); – Leigh

    関連する問題