質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
86.12%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

受付中

入力文字数を、フロントエンドとバックエンドで統一する方法

nikuatsu
nikuatsu

総合スコア172

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

1回答

0リアクション

0クリップ

218閲覧

投稿2022/11/24 19:27

編集2022/11/24 19:38

前提

JavaScript・php・SQLで掲示板サイトを作成しているのですが、絵文字を含む文字数のカウントで苦慮しています。

実現したいこと

次の条件でコメント入力を可能にしたいです。

・絵文字を含む(書記素単位で)「最大500文字まで」にしたい
・カラムにはインデックスを貼る

(合字は気にしません。)

発生している問題

まずは、JavaScriptで500文字の検証は出来ました。
ライブラリ「grapheme-splitter」を使います。
https://github.com/orling/grapheme-splitter

そして、PHPでも出来ました。
関数grapheme_strlenを使います。
https://www.php.net/manual/ja/function.grapheme-strlen.php

しかし、SQLでは以下のように出来ません。

該当のソースコード・エラーメッセージ

SQLでは以下ソースコードとエラーメッセージになります。(実現したいのは500文字ですが、わかりやすくVARCHAR(10)にしています。)

SQL

-- ソースコード CREATE TABLE test_table ( id INT UNSIGNED NOT NULL AUTO_INCREMENT ,content VARCHAR(10) CHARACTER SET utf8mb4 NOT NULL ,PRIMARY KEY (id) ,INDEX idx_test_table_01 (content) ); INSERT INTO test_table ( content ) VALUES ( 'abcdefghi🏴󠁧󠁢󠁥󠁮󠁧󠁿' ); -- 旗の絵文字のバイト数にご注意ください -- エラーメッセージ -- #1406 - Data too long for column 'content' at row 1

上記の'abcdefghi🏴󠁧󠁢󠁥󠁮󠁧󠁿'は、JavaScriptとPHPでは10になるのですが、SQLのVARCHAR(10)ではエラーになってしまうのです。

確認したこと

まず、DB接続はnew PDOで行っておりますが、そのcharsetutf8mb4でした。

そして、SHOW VARIABLES LIKE '%char%';を実行し、character_set_serverutf8mb4でした。

試したこと1 ( COLLATE 指定 )

次のALTER TABLEを実行しても変わりありませんでした。

sql

ALTER TABLE test_table MODIFY content VARCHAR(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; ALTER TABLE test_table MODIFY content VARCHAR(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

試したこと2 ( CHAR_LENGTH でのカウント )

SQLだけで整合が取れないなら、SQLだけで文字数のカウントを行う次のCHAR_LENGTHというアプローチも考えられます。が、しかしこれは「最大500文字まで」を実現することができません。
ユーザーにとって(書記素単位では)🏴󠁧󠁢󠁥󠁮󠁧󠁿は1文字なのに、これではそういったカウントができないのです。

php

<?php function getCharLength($str) { $mysqli = new MySQLi('db_host', 'db_user', 'db_pass', 'db_name'); $mysqli->set_charset('utf8mb4'); $sql = sprintf('SELECT CHAR_LENGTH("%s")', $mysqli->real_escape_string($str)); $result = (int)$mysqli->query($sql)->fetch_column(); $mysqli->close(); return $result; }

難しいポイント

難しいのは「最大500文字まで」という点です。

もし「最大10文字まで」ならJavaScriptとphpで10文字をカウントする検証を挟み、SQLはVARCHAR(100)にでもしておけば済む話です。もし🏴󠁧󠁢󠁥󠁮󠁧󠁿を10個入力されても問題ありません。

しかし「最大500文字まで」なので、もし🏴󠁧󠁢󠁥󠁮󠁧󠁿を500個入力されたとき、JavaScriptとphpでは問題なく500文字なのに、SQLでは768を超えてしまうという点です。(SQLでインデックスを貼るとVARCHAR(768)が限度)

ツールのバージョン

php: 8.1
MySQL: 5.7

以下のような質問にはリアクションをつけましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

リアクションが多い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

maisumakun

2022/11/24 23:52

> SQLでインデックスを貼るとVARCHAR(768)が限度 設定次第でその上限は外せるという情報もありましたが、そういう手段は取れないのでしょうか?
nikuatsu

2022/11/25 02:21

いえ、そういう手段があれば是非知りたいです。 早速検索し次の3つの手段を見つけましたが、それぞれ微妙な印象です。 https://blog.e2info.co.jp/2017/04/17/mysqlのインデックスサイズに767byteまでしかつかえない/ 1:絵文字を諦める → 諦めたくありません 2:191バイトにする → 768以上使いたいのに、191にしてどうするのか、理解ができません 3:innodb_large_prefix → レンタルサーバーのため権限なしです もしmaisumakun様の方で他にお心当たりございましたらご教示いただけませんでしょうか。
maisumakun

2022/11/25 02:27

あと、全文にインデックスを入れたいのはどんな事情でしょうか(プレフィックスインデックスでは不足する状況でしょうか)。
nikuatsu

2022/11/25 02:36

検索したいという事情でインデックスを条件にしたのですが、プレフィックスインデックスというのを初めて知りました。アドバイスありがとうございます。 早速調べてみると以下見つけました。 http://hono-linux.seesaa.net/article/416490499.html どうやらテストデータが必要なようなので、いくつかINSERTした上でまたコメントさせて頂ければと思います。
maisumakun

2022/11/26 04:44

> 検索したいという事情でインデックスを条件にしたのですが 完全一致以外の検索をかけたいのであれば、全文検索インデックスのほうが適当かもしれません。
nikuatsu

2022/12/03 07:04

なるほど。全文検索インデックスというのも良さそうに思えてきました。取り組んで比べてみたいと思います。ありがとうございます。

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
86.12%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。