こんにちは!プログラマーやってます。kazです。
先日もらった新しい名刺の肩書が「システムエンジニア」になっていて、驚いている今日この頃。
インフラできるようにならないと。。。

さて。何を書こうか考えたのですが、大それたことを書けるほどのスキルも経験もないので、このあいだハマったところを備忘録的に書いておこうかと思います。

マスターデータのID変更依頼

ここのところ、管理画面を作っているのですが、あるとき、登録するデータのIDが変更できるようにしてほしいとの依頼がありました。

問題①:インサートエラー

symfonyを使っているので、カンタンカンタン♪ $obj->setId($a[‘id’]); これでOKかと思いきや、こんなエラーが。。。。

Cannot insert a value for auto-increment primary key (○○.ID)

つまりは、オートインクリメントなプライマリーキーにはインサートできないよってこと。
DBでプライマリーキーやオプションの設定はもちろんしてありますが、そもそもsymfonyでは、自動的にオートインクリメントなプライマリーキーidが付加されます。

その値は変えられないのですね。
でも変えたい。

続きを読む

解決策

エラーが出力されたのは、データをinsertする、doInsertというメソッド。
これはBaseなので、ここを書き換えてもbuild-modelすれば元に戻っちゃう。
そこで、そのメソッドをまるっとコピーして子クラスに置き、対象箇所をコメントアウトして解決しました☆わい☆

無理矢理ですが、今回の管理画面はそもそものDB要件に反する仕様なので、強引にやってしまいました。
時には必要!きっと!

問題②:登録IDの順番

これで解決かと思いきや、試しに登録してみると、ちょっと問題が。
IDを指定して登録、変更は問題ないのですが、指定しない場合はどうなるのか。
たとえば3件目のデータを1つ飛ばしてID:4で登録した場合、auto_incrementの値は5になってしまうので、次にIDを指定しないで登録したら、ID:5に登録されます。

えー、飛ばしたidに登録したいよぅ。

解決策

なので、指定がない場合は、登録されていない一番小さいidで登録するって処理にしました。
具体的には、SQLで登録されていない一番小さいidを取得して、そのid指定で登録です。

そんな便利なSQLはこちら。↓

SELECT MIN(id + 1) as min FROM tablename WHERE (id + 1) NOT IN (SELECT id FROM tablename);

ポイントは、id+1にしているところです。
id+1のデータを、現在のデータ全てと照らし合わせて、存在しないものが飛ばされてるデータ。
その中の最小値ってことです。
これを取得して、idにセットしてあげればおっけー。
これは、全データを取得しているので、データがたくさんあればそれだけ重いし、場合によっては使えないかもしれません。

ただ、今回はマスターデータで件数がさほど多くないことがわかっているので採用しました。
もうまんたい。

もしかしたら、もっと簡単なやり方はあるかもです。
え、そんなことしないでも普通にできるよ?って方もいらっしゃると思います。

たぶん、そのやり方を知ったら、自分の知識のなさにげんなりしますが、このあいだ自分のできなさ具合に落ち込んでいたときに、同じ開発者の方に励ましてもらった一言をここで是非。

「知識はもちろん大事だけど、知識を詰め込むより、どうしたら良いプログラムが書けるのか、考え方の勉強をしたほうがいいよ」

調べてできることは、調べればいいから、それよりも考え方を学べと教えられました。
まだまだわからないことは沢山あるけれど、日々精進して頑張ります!
以上でしたー。

あわせて読みたい記事