$last_id = $pdo->lastInsertId(); echo $last_id;
複数の端末からの同時アクセスがあっても、自分が直前にINSERTしたAI(Auto Increment)の値を取得できる。
重複INSERTの防止等に利用する。
$last_id = $pdo->lastInsertId(); echo $last_id;
複数の端末からの同時アクセスがあっても、自分が直前にINSERTしたAI(Auto Increment)の値を取得できる。
重複INSERTの防止等に利用する。
MySQL8 でベースにする文字コードはutf8mb4_unicode_ci
照合順序は文字列の比較やソート順のルールのことです。各キャラクタセットごとに照合順序が定義されています。
-- SHOW COLLATIONS で一覧が見れる mysql> SHOW COLLATIONS; +----------------------------+----------+-----+---------+----------+---------+---------------+ | Collation | Charset | Id | Default | Compiled | Sortlen | Pad_attribute | +----------------------------+----------+-----+---------+----------+---------+---------------+ | armscii8_bin | armscii8 | 64 | | Yes | 1 | PAD SPACE | | armscii8_general_ci | armscii8 | 32 | Yes | Yes | 1 | PAD SPACE | | ascii_bin | ascii | 65 | | Yes | 1 | PAD SPACE | | ascii_general_ci | ascii | 11 | Yes | Yes | 1 | PAD SPACE | | big5_bin | big5 | 84 | | Yes | 1 | PAD SPACE | | big5_chinese_ci | big5 | 1 | Yes | Yes | 1 | PAD SPACE | | binary | binary | 63 | Yes | Yes | 1 | NO PAD | <snip>
MySQL 8.0 で、utf8mb4 の照合順序が増えました。以下の表で太字にしたものが、新規に追加されたものです。各文字列が、同一と扱われる場合は、○としています。
ci/cs
は Case [In]sensitive
の略で、as
は Acent Sensiteve
、ks
は Katakana Sensitive
の略です。
COLLATION | A、a | はは、ぱぱ | はは、ハハ | びょういん、びよういん | 🍣、🍺 | +、+ |
---|---|---|---|---|---|---|
utf8mb4_bin | × | × | × | × | × | × |
utf8mb4_0900_bin | × | × | × | × | × | × |
utf8mb4_unicode_ci | ○ | ○ | ○ | ○ | ○ | ○ |
utf8mb4_general_ci | ○ | × | × | × | ○ | × |
utf8mb4_unicode_520_ci | ○ | ○ | ○ | ○ | × | ○ |
utf8mb4_0900_ai_ci | ○ | ○ | ○ | ○ | × | ○ |
utf8mb4_0900_as_ci | ○ | × | ○ | ○ | × | ○ |
utf8mb4_ja_0900_as_cs | × | × | ○ | × | × | ○ |
utf8mb4_ja_0900_as_cs_ks | × | × | × | × | × | ○ |
アルファベットの大文字・小文字を区別しない要件で、どれが選ばれそうか・・・
utf8mb4_0900_as_ci
は「びょういん」「びよういん」が同一と扱われてしまい、いまいちに感じます。
そもそも、日本語の文字列比較やソート結果を網羅的に精査するのは現実的に可能なんでしょうか(上記の表以外にも考えないといけない、パターンがありそうです)。日本語には異字体・長音記号・漢数字・・・ちょっと思いつくだけでも、扱いに悩みそうな要素が多くあります。
絵文字が区別できないとは言え、utf8mb4_general_ci
にはずっと使ってきた実績と安心があります。
MySQL 8.0 でも utf8mb4_general_ci
を 引き続き使うケースが多いのではないでしょうか。
MySQL 8.0 で utf8mb4 のデフォルトの照合順序が utf8mb4_general_ci
から utf8mb4_0900_as_ci
に変更になりました。
あわせて、従来の3バイトUTF8、utf8(mb3) は deprecated になっています。
utf8mb4 に変換するときに COLLATE
を明示的に指定しないと、utf8_general_ci
から utf8mb4_0900_ai_ci
へとテーブルのデフォルト照合順序になってしまいます。
mysql> SELECT * FROM utf8t WHERE c1 = "ぱぱ"; Empty set (0.00 sec) mysql> ALTER TABLE utf8t CONVERT TO CHARACTER SET 'utf8mb4'; Query OK, 0 rows affected (0.03 sec) Records: 0 Duplicates: 0 Warnings: 0 -- 「ぱぱ」で「はは」がヒットしてしまう mysql> SELECT * FROM utf8t WHERE c1 = "ぱぱ"; +----+--------+ | pk | c1 | +----+--------+ | 1 | はは | +----+--------+ 1 row in set (0.00 sec) mysql> SHOW CREATE TABLE utf8t \G *************************** 1. row *************************** Table: utf8t Create Table: CREATE TABLE `utf8t` ( `pk` bigint unsigned NOT NULL AUTO_INCREMENT, `c1` varchar(255) DEFAULT NULL, UNIQUE KEY `pk` (`pk`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci 1 row in set (0.00 sec)
このように、COLLATE
を指定してALTERする必要があります。
mysql> ALTER TABLE utf8t CONVERT TO CHARACTER SET 'utf8mb4' COLLATE 'utf8mb4_general_ci'; Query OK, 0 rows affected (0.02 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> SHOW CREATE TABLE utf8t \G *************************** 1. row *************************** Table: utf8t Create Table: CREATE TABLE `utf8t` ( `pk` bigint unsigned NOT NULL AUTO_INCREMENT, `c1` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL, UNIQUE KEY `pk` (`pk`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci 1 row in set (0.00 sec)
同様に、SET NAMES
で照合順序を明示的に指定していない場合、MySQL 8.0 からは utf8mb4_0900_as_ci
が使われてしまいます。
# MySQL 8.0 以降は utf8mb4_0900_as_ci が使われる mysql> SET NAMES utf8mb4; # MySQL 8.0 以降は 明示的に utf8mb4_general_ci を指定する必要がある。 mysql> SET NAMES utf8mb4 COLLATE utf8mb4_general_ci;
原因は移行先サーバーのMySQLがMySQL5.5以下であるためです。例えば某Sサーバーなど..。utf8mb4_unicode_520_ciというcollationはMySQL5.6以上でしか利用できません。
現行のWordPressはutf8mb4_unicode_520_ciが使用できるサーバーではutf8mb4_unicode_520_ciを優先的に使用してインストールを行います。charsetとcollationを決定するwp-db.phpのコードは以下のようになっています。
/** * Determines the best charset and collation to use given a charset and collation. * * For example, when able, utf8mb4 should be used instead of utf8. * * @since 4.6.0 * @access public * * @param string $charset The character set to check. * @param string $collate The collation to check. * @return array The most appropriate character set and collation to use. */ public function determine_charset( $charset, $collate ) { if ( ( $this->use_mysqli && ! ( $this->dbh instanceof mysqli ) ) || empty( $this->dbh ) ) { return compact( 'charset', 'collate' ); } if ( 'utf8' === $charset && $this->has_cap( 'utf8mb4' ) ) { $charset = 'utf8mb4'; } if ( 'utf8mb4' === $charset && ! $this->has_cap( 'utf8mb4' ) ) { $charset = 'utf8'; $collate = str_replace( 'utf8mb4_', 'utf8_', $collate ); } if ( 'utf8mb4' === $charset ) { // _general_ is outdated, so we can upgrade it to _unicode_, instead. if ( ! $collate || 'utf8_general_ci' === $collate ) { $collate = 'utf8mb4_unicode_ci'; } else { $collate = str_replace( 'utf8_', 'utf8mb4_', $collate ); } } // _unicode_520_ is a better collation, we should use that when it's available. if ( $this->has_cap( 'utf8mb4_520' ) && 'utf8mb4_unicode_ci' === $collate ) { $collate = 'utf8mb4_unicode_520_ci'; } return compact( 'charset', 'collate' ); }
インポートするSQLファイルをエディタで開き、以下のように置き換えます。
utf8mb4_unicode_520_ci → utf8_general_ci
utf8mb4 → utf8
[参考]
2016〜2018年頃、レンタルサーバーでPHPやSQLのバージョンアップにより
いろんなオープンソースが対応できなくなるケースが多発しています。
EC-CUBE2系の場合、症状は様々ですが
・サイトが表示されない
・インストールが完了できない
・その他
原因の一つとして
SET SESSION storage_engine = InnoDB の実行時に以下のエラーで実行できないケースがあります。
/data/class/db/dbfactory/SC_DB_DBFactory_MYSQL.php の 末尾付近を編集します。
function initObjQuery(SC_Query &$objQuery) { // $objQuery->exec('SET SESSION storage_engine = InnoDB'); $objQuery->exec('SET SESSION default_storage_engine = InnoDB'); $objQuery->exec("SET SESSION sql_mode = 'ANSI'"); }
SQL文の半自動化に、さらなる進化がありました。
MySQLのカラムコメントを抽出することで
フォームの半自動化→7割自動化 を実現しました。
//構文設定 $stmt = $pdo->prepare('SHOW FULL columns FROM ' . wr_user); //実行 $stmt->execute(); $array_comment = array(); $i = 0; foreach($stmt->fetchAll() as $result): array_push($array_comment, $result['Comment']); $i ++; endforeach; var_dump($array_comment);
$statement = $pdo->query($sql); $item = $statement->fetch(PDO::FETCH_ASSOC); $i = 0; foreach($item as $key => $val){ if($i == 0){ $kanma = ''; }else{ $kanma = ','; } $key_text .= $kanma."`".$key."`"; $val_text .= $kanma."'".$_POST[$key]."'"; $i ++; } echo '<hr>'.$key_text.'<hr>'; echo $val_text.'<hr>'; $sql = "INSERT INTO `tb_staff` ($key_text) VALUES($val_text)"; echo $sql; $statement = $pdo->query($sql);
$pdo = new PDO('mysql:host = '.DB_SERVER.';dbname='.DB_NAME.';charset=utf8', DB_USER, DB_PASSWORD); $sql = "SELECT * FROM `wr_user` LIMIT 1"; $statement = $pdo->query($sql); $item = $statement->fetch(PDO::FETCH_ASSOC); $i = 0; foreach($item as $key => $val){ if($i == 0){ $kanma = ''; }else{ $kanma = ','; } $key_text .= $kanma."`".$key."`"; $val_text .= $kanma."'$".$key."'"; $i ++; } echo '<hr>'.$key_text.'<hr>'; echo $val_text.'<hr>'; $sql = "INSERT INTO `wr_user` ($key_text) VALUES($val_text)"; echo $sql;
$db = mysql_connect(DB_HOST.":".DB_PORT,DB_USER,DB_PASSWORD); // mysql_query("SET NAMES utf8"); mysql_set_charset('utf8'); mysql_select_db(DB_NAME, $db); $sql = "SELECT * FROM wr_posts LIMIT 1"; $rs = mysql_query($sql,$db); $item = mysql_fetch_assoc($rs); var_dump($item); $i = 0; foreach($item as $key => $val){ if($i == 0){ $kanma = ''; }else{ $kanma = ','; } $key_text .= $kanma."`".$key."`"; $val_text .= $kanma."'$".$key."'"; $i ++; } echo '<hr>'.$key_text.'<hr>'; echo $val_text.'<hr>';
自動生成の例
INSERT INTO `wr_user`
(`user_id`,`f1`,`f2`,`f3`)
VALUES
(‘exampleuser_id’,’examplef1′,’examplef2′,’examplef3′)
MySQLのフィールド名(カラム名)をSQL文用に自動で整形する。
$sql = "SELECT * FROM `dtb_customer` LIMIT 1"; $rs = mysql_query($sql,$db); $item = mysql_fetch_assoc($rs); // Key を配列化 $key_arr = array(); foreach($item as $key => $val){ echo $key."<br>"; }
$sql = "SELECT * FROM `dtb_products` LIMIT 1"; $rs = mysql_query($sql,$db); $item = mysql_fetch_assoc($rs); // Key を配列化 $key_arr = array(); foreach($item as $key => $val){ // echo $key."=>".$val."<br>"; // 試験表示 // array_push($key_arr, $key); echo "`".$key."`,"; }
php5〜php7
Database に接続
$pdo = new PDO('mysql:host='.DB_SERVER.';dbname='.DB_NAME.';charset=utf8', DB_USER, DB_PASSWORD);
ヒットがユニークの場合
$sql = "SELECT * FROM `tb_hogehoge`"; $statement = $pdo->query($sql); $item = $statement->fetch(PDO::FETCH_ASSOC); var_dump($item);
Roop の場合
$sql = "SELECT * FROM `tb_hogehoge`"; foreach($pdo->query($sql) as $item) { var_dump($item); }
↓php7 から使えなくなる。
$db = mysql_connect(DB_SERVER.":".DB_PORT,DB_USER,DB_PASSWORD); // mysql_query("SET NAMES utf8"); mysql_set_charset('utf8'); mysql_select_db(DB_NAME, $db); $sql1 = "SELECT * FROM `dtb_category` WHERE `category_id` = '$_GET[category_id]'"; $rs1 = mysql_query($sql1,$db); $item1 = mysql_fetch_assoc($rs1);
複数のテーブルを結合して、一つのテーブルのように見立てて、WHEREできる。
tb_menber
menber_id name birthday address
tb_profile
tall blood hobby
SELECT * FROM `tb_member` INNER JOIN `tb_profile`
すると
menber_id name birthday address tall blood hobby
に対して WHERE文が使える
SELECT * FROM `table_name1` INNER JOIN `table_name2` ON table_name1.hoge_id = table_name2.dore_id
同じフィールド名があるときは「table_name.culumn_name」とするが
table_name.culumn_name OK
`table_name.culumn_name` NG
シングルクォーテーションでくくってはダメらしい。
phpMyadminで「Cannot load or save configuration」とエラーが出ることがある。
phpMyadmin の直下に config というディレクトリを作れば解決する。
AUTO_INCREMENTの値として代入する数値は「’」コロンで囲まない。
$sql = "ALTER TABLE `dtb_products_class_product_class_id_seq` AUTO_INCREMENT = 777";
ついでに
EC-CUBE のあるバージョンで発生した事例。
CSVによる商品登録のさい
dtb_products_class_product_class_id_seq や dtb_products_product_id_seq において
・AUTO_INCREMENT を更新する
・sequence を更新する
両方更新しないと管理画面からの商品登録でエラーになる。
ユーザー名やパスワードが間違っていない。
config.inc.php が間違っていない。
ログインがエラーにならないのに
ログイン画面に戻ってしまう。
ブラウザによっては「アクセスが拒否されました」と表示される。
つまり、パスワード云々ではなく、拒否される
権限が無いのね。
試しに
phpMyadmin/setup にアクセスしてみる。
↓こんなエラーだ
session_start(*************): open failed: Permission denied (13)
セッションが書き込めないのね、ということで
/var/lib/php/session のパーミッションを確認する
[root@hogehoge php]# ls -l
drwxrwx— 2 apache apache session
apache からの書き込みがOKでも動かない
動いているサーバーの設定を見てみると
webユーザーにも許可が出ている。
webユーザーも読み書きできるようにパーミッションを変えたら
phpMyadmin が無事に動きました。
EC-CUBEやWordpressは動いていたので、session_save_path を疑いませんでしたが
彼らは session_save_path を指定して権限を付与している。
phpMyadmin はデフォルトのsession_save_path を使っている。
session_save_path を指定して、権限を付与するのもOKってことですね。
データベースのオーバーヘッドは、INSERT、DELETE、UPDATEを行っているうちにできるゴミ(未使用)領域のようなものです。
これを解消するためには、テーブルの最適化が必要です。
phpMyAdminからDB表示、画面一番下の「オーバーヘッドのあるテーブルを確認」→チェックが入る→ドロップダウンリストから「テーブルを最適化する」、で実行できます。
WHEREで大文字小文字が区別されないなんて迷惑な機能があります。
大文字小文字を区別するには条件式の前に”INARY”を付加するといいらしい。
SELECT * FROM `dtb_coupon` WHERE BINARY `coupon_code` = ‘$_POST[use_coupon]’ AND `del_flg` = ‘0’
EC-CUBEなどで、カテゴリIDや商品IDを指定したいということもあるようです。
AUTO_INCREMENT(自動採番)を採用しているのは、指定する必要性が考えられないからです。
番号を指定したいというご要望も多いですね。
理由は聞かないことにしています。
辻褄の合う理由など存在しないのですから、聞いて腹だ立つのなら、聞かずに対応してしまいましょう。
操作は至って簡単!
ALTER TABLE <テーブル名> AUTO_INCREMENT = 1;
関連テーブルのIDの変更もお忘れなく…
テープルのデータごと複製する。
create table NEW_TABLE_NAME as select * from ORG_TABLE_NAME
チカッパサーバーでのdumpファイルのインポートエラー
/*!40101 SET [ここはいろいろ] */;
こんなエラーが出て、ダンプのインポートが出来ない!
該当箇所を削除したら通った。
そういうことかぁ _φ( ̄ー ̄ )メモメモ
UPDATE テーブル SET カラム=REPLACE (カラム,"OLD文字列","NEW文字列");
受注管理でスターテスをリセットするSQL文
UPDATE `dtb_order` SET `status`='1', `deliv_no`='', `commit_date`='0000-00-00 00:00' LIMIT 20
UPDATE `dtb_order` SET `status` = '6' LIMIT 30 ;
フィールド名を勝手に抽出し、
POSTがあれば、POSTを優先
無ければDBを優先
これを勝手に行うソースコード
この記事に出会ったあなたはラッキーです。
// テーブル抽出(1レコードのみ) $sql = "SELECT * FROM `TABLE_NAME` LIMIT 1"; $statement = $pdo->query($sql); $item = $statement->fetch(PDO::FETCH_ASSOC); // Key を配列化 $key_arr = array(); foreach($item as $key => $val){ // echo $key."=>".$val."<br>"; // 試験表示 array_push($key_arr, $key); } // POST があれば変数に代入、無ければテーブルから変数に代入 $i="0"; while($key_arr[$i]!=""){ $value=$key_arr[$i]; // POST があれば変数に代入 if(($_POST[$value]!="") && ($_POST[$value]!="NULL")){ $$value=$_POST[$value]; // 無ければテーブルから変数に代入 }else{ $$value=$item[$value]; } $i ++; }
「アップロードしようとしたファイルが大きすぎるようです」とエラー場出る場合
「php.ini」の以下の設定を変更することに!
memory_limit =8M
post_max_size =8M
upload_max_filesize =8M
create table `NEW_TABLE_NAME` LIKE `BASE_TABLE_NAME`;
ALTER TABLE 既存のテーブル名 RENAME TO 新しいテーブル名;
SELECT * FROM `table_name` WHERE `field_name` = 'hoge' ORDER BY `field_name` DESC
「field_name」でソートします。
「DESC」で逆順になります。
複数フィールドも指定できます。
SELECT * FROM tb_name WHERE hoge = ‘***’ ORDER BY Field1,Field2,Field3 ASC
ひとつはPPMにCPANを登録する事。
メニューの「Edit」→「Reference」→「Repositories」にて「Name」は適当に、「Location」に「http://cpan.uwinnipeg.ca/PPMPackages/10xx/」と入力して「Add」ボタンをクリックして登録。
これでCPANに接続しする事ができ、CPANからもモジュールをダウンロードする事ができる。
ふたつ目はコマンドプロンプトから「perl -MCPAN -e shell」と入力。
これはCPANとコマンドで対話する事ができるシェルコマンド。
「cpan>」の後に「install DBD::mysql」と入力してモジュールをダウンロード&インストールするのだ。
////////////////
// 比較演算子 //
////////////////
where フィールド名 = ‘値’ レコードが値と等しい場合
where フィールド名 <> ‘値’ レコードが値と等しくない場合
where フィールド名 > ‘値’ レコードが値よりも大きい場合
where フィールド名 >= ‘値’ レコードが値以上である場合
where フィールド名 < '値' レコードが値より小さい場合
where フィールド名 <= '値' レコードが値以下である場合
////////////////////
// その他の演算子 //
////////////////////
where フィールド名 between '値1' and '値2'
レコードが値1と値2の間である場合値1と値2も含む
where フィールド名 in ('値1', '値2'...)
レコードがいずれかの値である場合複数の値を指定できる
where フィールド名 is null
レコードがnull値である場合
where フィールド名 is not null
レコードがnull値でない場合
where フィールド名 like '値%'
値から始まるレコードを検索前方一致
where フィールド名 like '%値%'
値を含むレコードを検索中間一致
where フィールド名 like '%値'
値で終わるレコードを検索後方一致
////////////////
// 論理演算子 //
////////////////
where 条件1 and 条件2 条件1でありかつまた条件2である場合(論理積)
where 条件1 or 条件2 条件1あるいは条件2である場合(論理和)
where not (条件) 条件でない場合(論理否定)
DBは郵便サイトからダウンロード
http://www.post.japanpost.jp/zipcode/dl/kogaki.html
SQL文(1)
テーブル生成
CREATE TABLE mtb_zipcode ( jis varchar(10) NULL, zip_old varchar(5) NULL, zip varchar(7) NULL, addr1_kana varchar(100) NULL, addr2_kana varchar(100) NULL, addr3_kana varchar(100) NULL, addr1 varchar(100) NULL, addr2 varchar(100) NULL, addr3 varchar(100) NULL, c1 int NULL, c2 int NULL, c3 int NULL, c4 int NULL, c5 int NULL, c6 int NULL )
SQL文(2)
データ挿入
vscファイルのエンコードを調整しておく
LOAD DATA LOCAL INFILE '/home/_DATABASE_BACKUP/KEN_ALL_UTF8.csv' INTO TABLE `tb_zip_code` FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
// MySQLに接続開始
$db = mysql_connect(DB_SERVER,DB_USER,DB_PASSWORD); mysql_query("SET NAMES utf8");
// ↑エンコード対策、これを書いておけば大概のサーバーで動く
$sql = "SELECT * FROM tb_main LIMIT 0,1"; $rs = mysql_query($sql3,$db); $item = mysql_fetch_assoc($rs3); foreach($item as $key => $val){ //echo $key."=>".$val.""; $key_arr[] =$key; }
Mysqlでのソート(数値の場合)普通に「ORDER BY フィールド名」では上1桁で判断されてしまう。
下記のようにすればOK!
SELECT * FROM `tb_movie` WHERE `driver_id` = '$driver_id' ORDER BY LPAD(grade5, 10, '0') DESC