MySQLで一重引用符、二重引用符、およびバッククォートを使用する場合


633

クエリを書くための最良の方法を学ぼうとしています。一貫性を保つことの重要性も理解しています。これまでは、一重引用符、二重引用符、バッククォートを無作為に使用してきました。

例:

$query = 'INSERT INTO table (id, col1, col2) VALUES (NULL, val1, val2)';

また、上記の例では、と考えてtablecol1val1、などの変数かもしれません。

これの基準は何ですか?職業はなんですか?

私はここで同様の質問に対する回答を約20分間読んでいますが、この質問に対する明確な回答はないようです。


16
これはMySQL固有の質問です。一般的なSQL(つまり、ISO / ANSI SQL)には異なる引用符のセットがあります。たとえば"tablename"、二重引用符は区切られた識別子用で、一重引用符はリテラル用です(たとえば)'this is a some text'。バックティックは、標準SQLでは使用されません。(識別子に二重引用符を含める必要がある場合は、二重引用符をとして入力し"odd""tablename"ます。同様に、リテラルのように二重単一引用符を使用します'Conan O''Brien'。)
jarlh

回答:


610

バッククォートはテーブルと列の識別子に使用されますが、識別子がMySQLの予約済みキーワードである場合、または識別子に空白文字または制限されたセットを超える文字が含まれている場合にのみ必要です(以下を参照)予約済みキーワードの使用を避けることをお勧めします可能な場合は列またはテーブルの識別子として、引用の問題を回避します。

VALUES()リストのように文字列値には一重引用符を使用する必要があります。MySQLでは文字列値の二重引用符もサポートされていますが、単一引用符は他のRDBMSで広く受け入れられているため、二重引用符の代わりに単一引用符を使用することをお勧めします。

MySQLはDATEDATETIMEリテラル値がのような文字列として単一引用符で囲まれていることも期待しています'2001-01-01 00:00:00'。相談する日付と時刻リテラルのハイフンを使用して、特定の選択肢で詳細はマニュアルを参照して、-日付文字列内のセグメントの区切り文字として。

したがって、例を使用すると、PHP文字列を二重引用符で囲み、値に単一引用符を使用します'val1', 'val2'NULLMySQLキーワードであり、特別な(非)値であるため、引用符で囲まれていません。

これらのテーブルまたは列の識別子は予約語ではなく、引用符を必要とする文字を利用していませんが、とにかくバッククォートで引用しました(これについては後で詳しく説明します)。

RDBMSにネイティブな関数(NOW()MySQLなど)は引用符で囲まないでください。それらの引数には、すでに説明した同じ文字列または識別子の引用規則が適用されます。

バックティック( `)
表と列───────┬─────┬──┬──┬──┬────┬──┬────┬──┬────┬──┬ ───────┐
                      ↓↓↓↓↓↓↓↓↓↓↓↓
$ query = " INSERT INTO` table`( `id`、` col1`、 `col2`、` date`、 `updated`)
                       VALUES(NULL、 'val1'、 'val2'、 '2001-01-01'、NOW()) ";
                               ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ 
引用符で囲まれていないキーワード─────┴┴┴┘│││││││││││
単一引用符( ')の文字列───────────┴────┴──┴────┘│││││││
単一引用符( ')日付───────────────────────────┴──────────┘││││ │
引用符で囲まれていない関数─────────────────────────────────────────┴┴┴┴┘    

可変補間

変数の引用パターンは変更されませんが、変数を文字列で直接補間する場合は、PHPで二重引用符で囲む必要があります。SQLで使用する変数を適切にエスケープしたことを確認してください。(SQLインジェクションに対する保護として、代わりに準備済みステートメントをサポートするAPIを使用することをお勧めします)。

//いくつかの変数の置換で同じこと
//ここでは、変数テーブル名$ tableがバックティック引用され、変数
// VALUESリストでは単一引用符で囲まれています 
$ query = "INSERT INTO` $ table`( `id`、` col1`、 `col2`、` date`)VALUES(NULL、'$ val1''$ val2''$ date') ";

準備されたステートメント

準備されたステートメントを使用する場合は、ドキュメントを参照して、ステートメントのプレースホルダーを引用する必要があるかどうかを判断してください。PHP、PDO、およびMySQLiで利用できる最も人気のあるAPI は、他の言語で準備されたほとんどのステートメントAPIと同様に、引用符で囲まれていないプレースホルダーを想定しています。

// PDO example with named parameters, unquoted
$query = "INSERT INTO `table` (`id`, `col1`, `col2`, `date`) VALUES (:id, :col1, :col2, :date)";

// MySQLi example with ? parameters, unquoted
$query = "INSERT INTO `table` (`id`, `col1`, `col2`, `date`) VALUES (?, ?, ?, ?)";

識別子でのバックティック引用を必要とする文字:

MySQLのドキュメントよれば、次の文字セットを使用して識別子を引用(バックティック)する必要はありません。

ASCII:([0-9,a-z,A-Z$_]基本的なラテン文字、数字0-9、ドル、アンダースコア)

たとえば、空白を含む、テーブルまたは列の識別子としてそのセット以外の文字を使用できますが、それらを引用符(バックティック)で囲む必要あります。


43
" しかし、単一引用符は他のRDBMSでより広く受け入れられています"-文字列リテラルに単一引用符を使用することは、SQL標準によって定義(および必須)されています
a_horse_with_no_name

@a_horse_with_no_name ANSI MySQLを使用する人はほとんどいない(文字列連結の '|'-本当に?)
Good Person

3
これは真実ではありません:「MySQLはDATEおよびDATETIMEリテラル値が '2001-01-01 00:00:00'のような文字列として単一引用符で囲まれていることも期待しています」
Kick_the_BUCKET

3
@evilReiko MySQLのドキュメントは、エイリアスの引用を明確に扱っていないようです。エイリアスのシングル、ダブル、またはバックティックを受け入れますが、異なるANSI SQLモードの影響を受ける可能性があります。エイリアスの引用に必要なSQL仕様がわからない-個人的な好み:一貫性を保つために、列識別子と同じように引用します。つまり、必要に応じてバックティックするか、引用しない場合はそのままにします。エイリアスに一重引用符や二重引用符を使用しません。
Michael Berkowski、2017

2
@GuneyOzsanはい、非常に脆弱です。受け入れ可能なテーブル名のリストに対して検証されていない限り、テーブル名に変数を使用しないでください。許可される名前の配列を作成し、変数がリスト内の何かと一致することを確認して、安全に使用できるようにします。そうしないと、テーブル名変数を安全にエスケープして使用できません。
Michael Berkowski、2018年

121

MySQLには2種類の引用符があります。

  1. ' 文字列リテラルを囲むため
  2. ` テーブル名や列名などの識別子を囲むため

そして"、特別なケースがあります。MySQLサーバーに応じて、一度に上記の目的のいずれかに使用できますsql_mode

  1. デフォルトでは、次の"ように文字を使用して文字列リテラルを囲むことができます。'
  2. ANSI_QUOTESモード"文字が同じように、識別子を囲むために使用することができます`

次のクエリは、SQLモードに応じて異なる結果(またはエラー)を生成します。

SELECT "column" FROM table WHERE foo = "bar"

ANSI_QUOTESは無効です

クエリは、列が文字"column"fooと等しい文字列リテラルを選択します"bar"

ANSI_QUOTESが有効

クエリは、列columnが列fooと等しい列を選択しますbar

何を使うべきか

  • "コードがSQLモードから独立するように、使用を避けることをお勧めします
  • 識別子は常に良い方法であるため、常に引用符で囲んでください(SOに関するいくつかの質問でこれを議論してください)

32

(質問のSQLの性質に関して上記の良い答えがありますが、これはPHPを初めて使用する場合にも関連する可能性があります。)

おそらく、PHPが単一引用符と二重引用符で囲まれた文字列を別々に処理することを言及することが重要です...

一重引用符で囲まれた文字列は「リテラル」であり、ほとんどWYSIWYG文字列です。二重引用符で囲まれた文字列は、可能な変数置換のためにPHPによって解釈されます(PHPのバッククォートは正確には文字列ではなく、シェルでコマンドを実行して結果を返します)。

例:

$foo = "bar";
echo 'there is a $foo'; // There is a $foo
echo "there is a $foo"; // There is a bar
echo `ls -l`; // ... a directory list

23

バッククォートは、一般的に示すために使用されているidentifierと同様になり、安全誤って使用してからの予約済みキーワード

例えば:

Use `database`;

ここで、バックティックは、サーバーdatabaseが実際にはデータベースの識別子ではなくデータベースの名前であることをサーバーが理解するのに役立ちます。

テーブル名とフィールド名についても同じことができます。データベース識別子をバッククォートで囲む場合、これは非常に良い習慣です。

この回答をチェックしてバックティックの詳細を理解してください。


次に、二重引用符と単一引用符についてです(Michaelはすでにそれについて言及しています)。

ただし、値を定義するには、一重引用符または二重引用符を使用する必要があります。別の例を見てみましょう。

INSERT INTO `tablename` (`id, `title`) VALUES ( NULL, title1);

ここでは、意図的にtitle1を引用符で囲むことを忘れています。これで、サーバーはをtitle1列名(つまり、識別子)として受け取ります。したがって、それが値であることを示すには、二重引用符または一重引用符を使用する必要があります。

INSERT INTO `tablename` (`id, `title`) VALUES ( NULL, 'title1');

現在、PHPと組み合わせて、二重引用符と単一引用符を使用すると、クエリの記述時間がはるかに簡単になります。質問のクエリの修正版を見てみましょう。

$query = "INSERT INTO `table` (`id`, `col1`, `col2`) VALUES (NULL, '$val1', '$val2')";

さて、PHPで二重引用符を使用して、変数を行います$val1と、$val2これは完全に有効なクエリを作成、それらの値を使用します。お気に入り

$val1 = "my value 1";
$val2 = "my value 2";
$query = "INSERT INTO `table` (`id`, `col1`, `col2`) VALUES (NULL, '$val1', '$val2')";

作る予定です

INSERT INTO `table` (`id`, `col1`, `col2`) VALUES (NULL, 'my value 1', 'my value 2')

15

MySQLでは、これらのシンボルは、クエリを区切るために使用されている`"'()

  1. "または'紐状の値を囲むために使用されている"26-01-2014 00:00:00"かを'26-01-2014 00:00:00'。これらのシンボルは文字列だけのためのものである、などの機能を集約していないnowsumまたはmax

  2. ` テーブルや列の名前を囲むために使用されます。例: select `column_name` from `table_name` where id='2'

  3. (そして)単にクエリの一部を囲みます select `column_name` from `table_name` where (id='2' and gender='male') or name='rakesh'


13

MySQLとPHPの文字列リテラルは同じです。

文字列はバイトまたは文字のシーケンスであり、単一引用符( "'")または二重引用符( "" ")の文字で囲まれます。

したがって、文字列に一重引用符が含まれている場合は、二重引用符を使用して文字列を引用できます。二重引用符が含まれている場合は、一重引用符を使用して文字列を引用できます。ただし、文字列に一重引用符と二重引用符の両方が含まれている場合は、文字列を引用するために使用した引用符をエスケープする必要があります。

ほとんどの場合、SQL文字列値には一重引用符を使用するため、PHP文字列には二重引用符を使用する必要があります。

$query = "INSERT INTO table (id, col1, col2) VALUES (NULL, 'val1', 'val2')";

また、PHPの二重引用符で囲まれた文字列で変数を使用できます。

$query = "INSERT INTO table (id, col1, col2) VALUES (NULL, '$val1', '$val2')";

しかし、$val1または$val2単一引用符が含まれていると、SQLが正しくなくなります。したがって、SQLで使用する前にエスケープする必要があります。それがmysql_real_escape_string目的です。(ただし、準備されたステートメントの方が優れています。)


12

PHPとMySQLの組み合わせでは、二重引用符と一重引用符を使用すると、クエリを書く時間が非常に簡単になります。

$query = "INSERT INTO `table` (`id`, `col1`, `col2`) VALUES (NULL, '$val1', '$val2')";

ここで、MySQLクエリに直接ポスト変数を使用していると仮定し、次のように使用します。

$query = "INSERT INTO `table` (`id`, `name`, `email`) VALUES (' ".$_POST['id']." ', ' ".$_POST['name']." ', ' ".$_POST['email']." ')";

これは、PHP変数をMySQLに使用するためのベストプラクティスです。


したがって、二重引用符は柔軟ですが、識別子として使用できません。
rhavendc 2016年

エスケープされていないユーザー入力をクエリで直接使用しないでください。
jankal 16

@jankalこれは単なる例です。直接のユーザー入力を使用している場合は、nを指定します...........
vipul sorathiya

@vipulsorathiya POST変数をエスケープする必要があることを回答で指定してください。クエリで直接使用するように指示しています。これを試してみる初心者には悪い...
RFLdev 2017

12

ここには多くの役立つ答えがあり、一般に2つのポイントに達します。

  1. BACKTICKS( `)は識別子名の前後に使用されます。
  2. SINGLE QUOTES( ')は値の周りに使用されます。

そして@MichaelBerkowskiが言ったように

バッククォートはテーブルと列の識別子に使用されますが、識別子がMySQL予約済みのキーワードである場合、または識別子に空白文字または制限されたセットを超える文字が含まれている場合にのみ必要です(以下を参照)。可能な場合は列またはテーブルの識別子。引用の問題を回避します。

ただし、識別子が予約済みキーワードにならない場合や、制限されたセットを超えて空白文字を含めることができない場合もありますが、それらの周囲には必ずバッククォートが必要です。

123E10有効な識別子名ですが、有効なINTEGERリテラルでもあります。

[このような識別子名の取得方法については詳しく説明しません]という名前の一時テーブルを作成するとし123456e6ます。

バックティックにエラーはありません。

DB [XXX]> create temporary table `123456e6` (`id` char (8));
Query OK, 0 rows affected (0.03 sec)

バックティックを使用していないときのエラー。

DB [XXX]> create temporary table 123451e6 (`id` char (8));
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '123451e6 (`id` char (8))' at line 1

ただし、123451a6完全に細かい識別子名です(バックティックなし)。

DB [XXX]> create temporary table 123451a6 (`id` char (8));
Query OK, 0 rows affected (0.03 sec)

これも完全に1234156e6指数です。


10

テーブルの列と値が変数の場合、2つの方法があります。

二重引用符""で完全なクエリ:

$query = "INSERT INTO $table_name (id, $col1, $col2)
                 VALUES (NULL, '$val1', '$val2')";

または

 $query = "INSERT INTO ".$table_name." (id, ".$col1.", ".$col2.")
               VALUES (NULL, '".$val1."', '".$val2."')";

一重引用符付き''

$query = 'INSERT INTO '.$table_name.' (id, '.$col1.', '.$col2.')
             VALUES (NULL, '.$val1.', '.$val2.')';

``列/値の名前がMySQLの予約済みキーワードに似ている場合は、バックティックを使用します。

注:列名をテーブル名で表す場合は、次のようにバックティックを使用します。

`table_name``column_name` <-注:. バックティックから除外します。


8

VALUES()リストのように、文字列値には一重引用符を使用する必要があります。

バックティックは通常、識別子を示すために使用され、予約済みのキーワードを誤って使用しないようにするためにも使用されます。

PHPとMySQLの組み合わせでは、二重引用符と単一引用符を使用すると、クエリの作成時間が非常に簡単になります。


4

(十分に説明された)すべての回答に加えて、次のような言及はありませんでした。私はこのQ&Aに頻繁にアクセスしています。

手短に; MySQLは、独自のテーブル/列で数学を実行したいと考え、「電子メール」などのハイフンをe マイナス と解釈しmailます。


免責事項:データベースの操作にまったく慣れておらず、すでに説明されている技術用語を理解していない可能性がある場合は、「FYI」タイプの回答としてこれを追加すると思いました。


1

SQLサーバーおよびMySQL、PostgreySQL、Oracleは二重引用符( ")を認識しません。したがって、クエリには二重引用符(")を含めず、単一引用符( ')のみを使用する必要があります。

Back-trip( `)はSQLでの使用がオプションであり、テーブル名、DB名、および列名に使用されます。

MySQLを呼び出すためにバックエンドでクエリを記述しようとしている場合は、二重引用符( ")または単一引用符( ')を使用して、次のような変数にクエリを割り当てることができます。

let query = "select id, name from accounts";
//Or
let query = 'select id, name from accounts';

それらがwhereクエリ内のステートメントであるinsertか、update文字列である値または値、あるいはその両方を試行している場合は、次のようにこれらの値に単一引用符( ')を使用します。

let querySelect = "select id, name from accounts where name = 'John'";
let queryUpdate = "update accounts set name = 'John' where id = 8";
let queryInsert = "insert into accounts(name) values('John')";

//Please not that double quotes are only to be used in assigning string to our variable not in the query
//All these below will generate error

let querySelect = 'select id, name from accounts where name = "John"';
let queryUpdate = 'update accounts set name = "John" where id = 8';
let queryInsert = 'insert into accounts(name) values("John")';

//As MySQL or any SQL doesn't understand double quotes("), these all will generate error.

二重引用符( ")と単一引用符( ')を使用するときにこの混乱を避けたい場合は、単一引用符(')を使用することをお勧めします。これには次のようなバックスラッシュ()が含まれます。

let query = 'select is, name from accounts where name = \'John\'';

double( ")またはsingle( ')の引用の問題は、動的な値を割り当て、次のような文字列連結を実行する必要がある場合に発生します。

let query = "select id, name from accounts where name = " + fName + " " + lName;
//This will generate error as it must be like name = 'John Smith' for SQL
//However our statement made it like name = John Smith

//In order to resolve such errors use
let query = "select id, name from accounts where name = '" + fName + " " + lName + "'";

//Or using backslash(\)
let query = 'select id, name from accounts where name = \'' + fName + ' ' + lName + '\'';

さらにクリアランスが必要な場合は、JavaScriptの引用符に従っください

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.