- 投稿日:2019-02-26T20:05:37+09:00
CakePHPでのDB更新処理の2つの場合(idで指定 or whereで指定)の方法について
バージョンはCakePHP3.2です。
DBはMySQLを使ってます。下記の条件についてそれぞれの方法を書いていきます
- idで更新するrowを指定する場合
- whereで更新するrowを指定する場合
1. idでupdateするrowを指定する場合
<?php use Cake\ORM\TableRegistry; // ~ 略 ~ // MembersTableの読み込み $this->loadModel('Members'); // DBとの通信開始 $this->Members->connection()->begin(); // updateするrowをidで指定 $qurey = $this->Members->get('10'); // updateするcolumnの値を代入 $qurey->address = 'Kanagawa'; $qurey->age = '21'; // dataがあれば更新,無ければ挿入を行いつつ、処理結果をresultに代入。 $result = $this->Members->save($query); if ( $result === false ) { // もし失敗したらロールバック $this->Members->connection()->rollback(); } else { // 失敗していなければコミット $this->Members->connection()->commit(); }
2. whereでupdateするrowを指定する場合
<?php use Cake\Datasource\ConnectionManager; use Cake\ORM\TableRegistry; // ~ 略 ~ // MembersTableの読み込み $this->loadModel('Members'); $connection = ConnectionManager::get('default'); // updateするcolumnの値を代入 $membernew = array( 'address' => 'Kanagawa', 'age' => '21' ); // DBとの通信開始 $this->Members->connection()->begin(); // 更新するrowをwhereで探して取得する。 $query = $this->Members->find() ->where(['name' => 'Gaku']) ->where(['address' => 'Tokyo']) ->where(['age' => '20']) ->first(); if(isset($query)) { // queryにデータがあれば更新処理にする。 $member = $this->Members->patchEntity($query, $membernew); } else { // データが無ければ挿入処理にする。 $member = $this->Members->newEntity($membernew); } // 上で指定した処理を実行しつつ結果を代入する $result = $this->Members->save($member); if ( $resource_result === false ) { // もし失敗したらロールバック $this->Members->connection()->rollback(); } else { // 失敗していなければコミット $this->Members->connection()->commit(); }以上です。
- 投稿日:2019-02-26T14:34:57+09:00
Slick+MySQLでdatetimeやtimestampをjava.time.*に変換したい【Slick3.3以降】
はじめに
この間怒りに任せてあげたSlickでいつの間にかjava.time.*がサポートされてた話ではMySQLの
datetime
やtimestamp
はjava.time.LocalDateTime
に相互変換されませんって話でした。
しかも以前はサポート対象外だったおかげて暗黙の変換を書いておけば問題なかったんですが、3.3以降、自分の環境ではjava.time.*
系の変換を書いちゃうとどっかで衝突すんのかコンパイルが通らなくなってしまいました(上記前記事参照)。という訳で今回はどうにかして変換できるようにしてみます。
環境
scala: 2.12
slick: 3.3型を作ってしまおう
しょうがないので間に型を咬ませます。
代表してdatetime
をサポートしてみます。case class MySQLDateTime(value: String) { def toLocalDateTime: LocalDateTime = LocalDateTime.parse(value, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) }回りくどい気もしますが、値として
datetime
をString
で保持し、LocalDateTime
として出力できるようにしています。テーブルではこんな感じ
class TestTable(tag: Tag) extends Table[Test](tag, "test") { // 抜粋 def testDate = column[MySQLDateTime]("test_date") // 抜粋 }このままでは当然
MySQLDateTime
型は変換できないのでコンパイルは通りません。暗黙の変換
上記テーブルに下記の暗黙の変換を追加します。
implicit lazy val mySqlDateTimeType: JdbcType[MySQLDateTime] with BaseTypedType[MySQLDateTime] = MappedColumnType.base[MySQLDateTime, java.sql.Timestamp]( t => java.sql.Timestamp.valueOf(t.value), u => MySQLDateTime(u.toLocalDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))) )テーブルからは
java.sql.Timestamp
として受けて相互変換可能としています。DateTimeFormatter...
云々はどこぞに固定値として生やした方が良いでしょう。おわりに
timestamp
やdate
、time
も同様に書くことができると思います。
- 投稿日:2019-02-26T10:01:51+09:00
Mysqlでカラム名を検索する
コマンド
とりあえず、コマンドが分かれば検索できるので最初に書いときます。
※mysqlで動かしましたが他のDBでは動かしてません。sqlselect * from information_schema.columns where COLUMN_NAME = "カラム名" and table_schema = "データベース名";これだけだと、表示されるselectが多いから適宜「*」を変えて検索
例
検索したいカラム名が含まれるテーブル名を検索したい時
sqlselect table_name, column_name from information_schema.columns where COLUMN_NAME = "カラム名" and table_schema = "データベース名";名称備忘
information_schema.columns
テーブル内のカラムに関する情報を表示してくれる。
以下のリンクが公式のサイト
mysalServerの公式
- 投稿日:2019-02-26T01:16:17+09:00
複合ユニークのうちの一つのカラムのint値をすでに使われてるint値に更新したい
MySQLでこういったテーブルとデータがあったとする。データに任意の順番をもたせたいが、順番の値は重複を許可したくないといったケースを想定している。下記テーブルでいくと
sort
カラムが順番の値を保持しているものとする。create table test( id int, test_id int, sort int, unique(test_id, sort) ); INSERT INTO `test` (`id`, `test_id`, `sort`) VALUES (1, 1, 0), (2, 1, 1), (3, 1, 2);idが3のレコードの
sort
を1にしたい場合、普通にupdateしようとすると、複合ユニークの制約によりエラーとなってしまう?しかし、下記のようにSQLを発行すると、値を重複させることなく更新をかけることが可能となる。
UPDATE test SET sort = (sort + 1) WHERE sort >= 1 ORDER BY sort DESC; UPDATE test SET sort = 1 WHERE id = 3;
sort
の値が1以上の値にすべて1をプラスし、空いた1のポジションにidが3のレコードが滑り込んでいるような形である。最初のupdate文で
ORDER BY sort DESC
を指定しているが、この指定があることで降順にレコードにupdateをかけられる。ASC
で処理をした場合は、もちろん複合ユニークの制約に引っかかってしまい、エラーとなってしまう。ORDER BY 句が指定されている場合は、指定されている順序で行が更新されます。
https://dev.mysql.com/doc/refman/5.6/ja/update.html
また、これとは別に、特定の
test_id
のレコードはすべてdeleteし、sort
の値を振り直してinsertし直すといった洗替する方法も考えられる。最初、バルクアップデート的なものでいけないかなと考え実際にやってみたが、残念ながらユニーク制約にひっかかってしまった。