เมื่อใดควรใช้เครื่องหมายคำพูดเดี่ยวเครื่องหมายคำพูดคู่และเครื่องหมายย้อนกลับใน MySQL
ฉันพยายามเรียนรู้วิธีที่ดีที่สุดในการเขียนแบบสอบถาม ฉันยังเข้าใจถึงความสำคัญของการมีความเสมอต้นเสมอปลาย จนถึงตอนนี้ฉันสุ่มใช้เครื่องหมายคำพูดเดี่ยวเครื่องหมายคำพูดคู่และการย้อนกลับโดยไม่ได้คิดอะไรเลย
ตัวอย่าง:
$query = 'INSERT INTO table (id, col1, col2) VALUES (NULL, val1, val2)';
นอกจากนี้ในตัวอย่างข้างต้นพิจารณาว่าtable
, col1
, val1
และอื่น ๆ อาจจะเป็นตัวแปร
มาตรฐานสำหรับสิ่งนี้คืออะไร? คุณทำอะไร?
ฉันอ่านคำตอบของคำถามที่คล้ายกันที่นี่มาประมาณ 20 นาทีแล้ว แต่ดูเหมือนว่าจะไม่มีคำตอบที่ชัดเจนสำหรับคำถามนี้
คำตอบ
Backticks ใช้สำหรับตัวระบุตารางและคอลัมน์ แต่จำเป็นก็ต่อเมื่อตัวระบุเป็นคีย์เวิร์ดที่สงวนไว้ของ MySQLหรือเมื่อตัวระบุมีอักขระเว้นวรรคหรืออักขระเกินชุดที่ จำกัด (ดูด้านล่าง) ขอแนะนำให้หลีกเลี่ยงการใช้คีย์เวิร์ดที่สงวนไว้ เป็นตัวระบุคอลัมน์หรือตารางเมื่อเป็นไปได้หลีกเลี่ยงปัญหาการอ้างสิทธิ์
ควรใช้เครื่องหมายคำพูดเดี่ยวสำหรับค่าสตริงเช่นในVALUES()
รายการ MySQL รองรับเครื่องหมายคำพูดคู่สำหรับค่าสตริงเช่นกัน แต่คำพูดเดี่ยวได้รับการยอมรับอย่างกว้างขวางจาก RDBMS อื่น ๆ ดังนั้นจึงเป็นนิสัยที่ดีที่จะใช้เครื่องหมายคำพูดเดี่ยวแทนที่จะเป็นคู่
MySQL ยังคาดหวังDATE
และDATETIME
ค่าตามตัวอักษรจะถูกยกมาเป็นสตริงเช่น'2001-01-01 00:00:00'
. ดูเอกสารตัวระบุวันที่และเวลาสำหรับรายละเอียดเพิ่มเติมโดยเฉพาะทางเลือกอื่น ๆ ในการใช้ยัติภังค์-
เป็นตัวคั่นเซ็กเมนต์ในสตริงวันที่
ดังนั้นการใช้ตัวอย่างของคุณผมจะอ้างดับเบิลสตริง PHP 'val1', 'val2'
และใช้คำพูดเดียวบนค่า NULL
เป็นคีย์เวิร์ด MySQL และ special (non) -value จึงไม่มีการอ้างถึง
ไม่มีตัวระบุตารางหรือคอลัมน์เหล่านี้เป็นคำสงวนหรือใช้ประโยชน์จากอักขระที่ต้องใช้การอ้างอิง แต่ฉันได้ยกมาด้วย backticks (เพิ่มเติมในภายหลัง ... )
NOW()
ไม่ควรยกฟังก์ชันที่เป็นของ RDBMS (เช่นใน MySQL) แม้ว่าอาร์กิวเมนต์จะอยู่ภายใต้กฎการอ้างอิงสตริงหรือตัวระบุเดียวกันที่กล่าวถึงแล้วก็ตาม
Backtick (`) ตารางและคอลัมน์───────┬─────┬──┬──┬──┬────┬──┬────┬──┬────┬──┬ ───────┐ ↓↓↓↓↓↓↓↓↓↓↓↓ $ query = " INSERT INTO" table` ("id`," col1`, "col2`," date`, "updated`) ค่า (NULL, 'val1', 'val2', '2001-01-01', NOW ()) "; ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ คีย์เวิร์ดที่ไม่มีเครื่องหมายคำพูด─────┴┴┴┘│││││││││││ สตริงที่มีเครื่องหมายอัญประกาศเดี่ยว (') ───────────┴────┴──┴────┘│││││││││││ Single-quoted (') DATE ───────────────────────────┴──────────┘││││ │ ฟังก์ชันที่ไม่ได้ใส่เครื่องหมายคำพูด─────────────────────────────────────────┴┴┴┴┘
การแก้ไขตัวแปร
รูปแบบการเสนอราคาสำหรับตัวแปรจะไม่เปลี่ยนแปลงแม้ว่าคุณตั้งใจจะแก้ไขตัวแปรในสตริงโดยตรง แต่ก็ต้องมีการอ้างถึงสองครั้งใน PHP ตรวจสอบให้แน่ใจว่าคุณได้หลีกเลี่ยงตัวแปรอย่างถูกต้องเพื่อใช้ใน SQL ( ขอแนะนำให้ใช้ API ที่รองรับคำสั่งที่เตรียมไว้แทนเพื่อป้องกันการแทรก SQL )
// สิ่งเดียวกันกับการแทนที่ตัวแปรบางอย่าง // ที่นี่ชื่อตารางตัวแปร $ table คือ backtick-quoted และตัวแปร // ในรายการ VALUES มีการยกมาครั้งเดียว $ query = "INSERT INTO` $ table` ("id`," col1`, "col2`," date`) VALUES (NULL, '$ val1' , '$ val2' , '$ date' ) ";
เตรียมงบ
เมื่อทำงานกับข้อความที่เตรียมไว้โปรดดูเอกสารประกอบเพื่อพิจารณาว่าจะต้องอ้างอิงตัวยึดคำสั่งหรือไม่ API ที่นิยมมากที่สุดใน PHP PDO และ MySQLi คาดว่าunquotedตัวยึดตำแหน่งเช่นเดียวกับ APIs งบเตรียมมากที่สุดในภาษาอื่น ๆ :
// 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 (?, ?, ?, ?)";
อักขระที่เรียกคืนการอ้างถึง backtick ในตัวระบุ:
ตามเอกสารของ MySQLคุณไม่จำเป็นต้องอ้างตัวระบุ (backtick) โดยใช้ชุดอักขระต่อไปนี้:
ASCII:
[0-9,a-z,A-Z$_]
(อักษรละตินพื้นฐาน, ตัวเลข 0-9, ดอลลาร์, ขีดล่าง)
คุณสามารถใช้อักขระที่อยู่นอกเหนือจากที่กำหนดเป็นตัวระบุตารางหรือคอลัมน์รวมถึงช่องว่างได้เช่นกัน แต่คุณต้องอ้าง (backtick)
นอกจากนี้แม้ว่าตัวเลขจะเป็นอักขระที่ถูกต้องสำหรับตัวระบุ แต่ตัวระบุไม่สามารถประกอบด้วยตัวเลขเพียงอย่างเดียว ถ้าพวกเขาทำพวกเขาจะต้องถูกห่อด้วยแบ็คติก
มีคำพูดสองประเภทใน MySQL:
'
สำหรับการปิดตัวอักษรสตริง`
สำหรับการใส่ตัวระบุเช่นชื่อตารางและคอลัมน์
แล้วมี"
ที่เป็นกรณีพิเศษ มันอาจจะใช้สำหรับหนึ่งในวัตถุประสงค์ดังกล่าวข้างต้นได้ตลอดเวลาขึ้นอยู่กับเซิร์ฟเวอร์ของ MySQL sql_mode:
- โดยค่าเริ่มต้น
"
ตัวละครที่สามารถใช้ในการใส่สายอักขระตัวอักษรเช่นเดียวกับ'
- ในANSI_QUOTESโหมด
"
สามารถใช้อักขระเพื่อปิดตัวระบุได้เช่นเดียวกับ`
แบบสอบถามต่อไปนี้จะให้ผลลัพธ์ที่แตกต่างกัน (หรือข้อผิดพลาด) ขึ้นอยู่กับโหมด SQL:
SELECT "column" FROM table WHERE foo = "bar"
ปิดใช้งาน ANSI_QUOTES
แบบสอบถามจะเลือกสตริงลิเทอรัล"column"
โดยที่คอลัมน์foo
เท่ากับสตริง"bar"
เปิดใช้งาน ANSI_QUOTES
แบบสอบถามจะเลือกคอลัมน์column
ที่คอลัมน์foo
เท่ากับคอลัมน์bar
เมื่อใดควรใช้อะไร
- ฉันขอแนะนำให้คุณหลีกเลี่ยงการใช้
"
เพื่อให้โค้ดของคุณไม่ขึ้นอยู่กับโหมด SQL - อ้างตัวระบุเสมอเนื่องจากเป็นแนวทางปฏิบัติที่ดี (คำถามค่อนข้างน้อยเกี่ยวกับ SO จะพูดถึงเรื่องนี้)
(มีคำตอบที่ดีข้างต้นเกี่ยวกับลักษณะ SQL ของคำถามของคุณ แต่สิ่งนี้อาจเกี่ยวข้องด้วยหากคุณยังใหม่กับ PHP)
บางทีอาจเป็นเรื่องสำคัญที่จะต้องพูดถึงว่า PHP จัดการสตริงที่ยกมาเดี่ยวและคู่ต่างกัน ...
สตริงที่มีเครื่องหมายอัญประกาศเดี่ยวเป็น 'ตัวอักษร' และเป็นสตริงแบบ WYSIWYG ค่อนข้างมาก สตริงที่ยกมาสองครั้งถูกตีความโดย PHP สำหรับการแทนที่ตัวแปรที่เป็นไปได้ (backticks ใน 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
backticks โดยทั่วไปจะใช้เพื่อระบุidentifier
และรวมทั้งจะปลอดภัยจากการตั้งใจใช้คำสงวน
ตัวอย่างเช่น:
Use `database`;
ที่นี่แบ็คทิกจะช่วยให้เซิร์ฟเวอร์เข้าใจว่าdatabase
แท้จริงแล้วคือชื่อของฐานข้อมูลไม่ใช่ตัวระบุฐานข้อมูล
สามารถทำได้เช่นเดียวกันสำหรับชื่อตารางและชื่อเขตข้อมูล นี่เป็นนิสัยที่ดีมากหากคุณรวมตัวระบุฐานข้อมูลของคุณด้วย backticks
ตรวจสอบคำตอบนี้เพื่อทำความเข้าใจเพิ่มเติมเกี่ยวกับ backticks
ตอนนี้เกี่ยวกับ Double quotes & Single Quotes (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')
ใน MySQL, สัญลักษณ์เหล่านี้ถูกนำมาใช้เพื่อกำหนดเขตแบบสอบถาม`
, "
, และ'
()
"
หรือ'
ใช้สำหรับการปิดค่าที่เหมือนสตริง"26-01-2014 00:00:00"
หรือ'26-01-2014 00:00:00'
. สัญลักษณ์เหล่านี้เป็นเพียงสำหรับสตริงไม่รวมฟังก์ชั่นเช่นnow
, หรือsum
max
`
ใช้สำหรับปิดชื่อตารางหรือคอลัมน์เช่นselect `column_name` from `table_name` where id='2'
(
และชิ้นส่วนที่แนบเพียงของแบบสอบถามเช่น)
select `column_name` from `table_name` where (id='2' and gender='male') or name='rakesh'
ตัวอักษรสตริงใน 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
มีไว้เพื่อ (แม้ว่าคำสั่งที่เตรียมไว้จะดีกว่าก็ตาม)
เมื่อใช้ร่วมกันระหว่าง 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
มีคำตอบที่เป็นประโยชน์มากมายที่นี่โดยทั่วไปจะสรุปเป็นสองประเด็น
- BACKTICKS (`) ใช้กับชื่อตัวระบุ
- SINGLE QUOTES (') ใช้กับค่าต่างๆ
และตามที่ @MichaelBerkowski กล่าว
Backticks ใช้สำหรับตัวระบุตารางและคอลัมน์ แต่จำเป็นก็ต่อเมื่อตัวระบุเป็น
MySQL
คีย์เวิร์ดที่สงวนไว้หรือเมื่อตัวระบุมีอักขระเว้นวรรคหรืออักขระเกินชุดที่ จำกัด (ดูด้านล่าง) ขอแนะนำให้หลีกเลี่ยงการใช้คีย์เวิร์ดที่สงวนไว้เป็น ตัวระบุคอลัมน์หรือตารางหากเป็นไปได้หลีกเลี่ยงปัญหาการอ้าง
มีบางกรณีที่ตัวระบุไม่สามารถเป็นคีย์เวิร์ดที่สงวนไว้หรือมีช่องว่างหรืออักขระเกินกว่าที่กำหนดไว้แต่จำเป็นต้องมีการแบ็คทิก
ตัวอย่าง
123E10
เป็นชื่อตัวระบุที่ถูกต้อง แต่ยังเป็นลิเทอINTEGER
รัลที่ถูกต้อง
[โดยไม่ต้องไปลงในรายละเอียดวิธีการที่คุณจะได้รับเช่นชื่อตัวระบุ] 123456e6
สมมติว่าผมต้องการที่จะสร้างตารางชั่วคราวชื่อ
ไม่มีข้อผิดพลาดเกี่ยวกับ backticks
DB [XXX]> create temporary table `123456e6` (`id` char (8));
Query OK, 0 rows affected (0.03 sec)
ข้อผิดพลาดเมื่อไม่ใช้ backticks
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
เป็นเลขเอกซ์โพเนนเชียลด้วย
หากคอลัมน์และค่าของตารางเป็นตัวแปรมีสองวิธี:
ด้วยเครื่องหมายคำพูดคู่""
แบบสอบถามที่สมบูรณ์:
$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`
<- หมายเหตุ: ไม่รวม.
จากขีดหลัง
ควรใช้เครื่องหมายคำพูดเดี่ยวสำหรับค่าสตริงเช่นในรายการ VALUES ()
โดยทั่วไปแล้ว Backticks จะใช้เพื่อระบุตัวระบุและยังปลอดภัยจากการใช้คำหลักที่สงวนไว้โดยไม่ได้ตั้งใจ
เมื่อใช้ร่วมกันระหว่าง PHP และ MySQL เครื่องหมายคำพูดคู่และเครื่องหมายคำพูดเดี่ยวทำให้เวลาในการเขียนแบบสอบถามของคุณง่ายขึ้นมาก
นอกจากคำตอบทั้งหมด (อธิบายอย่างดี) แล้วยังไม่มีการกล่าวถึงต่อไปนี้และฉันไปที่ถาม & ตอบนี้ค่อนข้างบ่อย
โดยสังเขป; MySQL คิดว่าคุณต้องการจะทำคณิตศาสตร์บนโต๊ะของตัวเอง / คอลัมน์และตีความขีดเช่น "อีเมล" เป็นลบe
mail
ข้อจำกัดความรับผิดชอบ:ดังนั้นฉันคิดว่าฉันจะเพิ่มสิ่งนี้เป็นคำตอบประเภท "FYI" สำหรับผู้ที่เพิ่งเริ่มทำงานกับฐานข้อมูลและอาจไม่เข้าใจข้อกำหนดทางเทคนิคที่อธิบายไว้แล้ว
เซิร์ฟเวอร์ SQL และ MySQL, PostgreySQL, Oracle ไม่เข้าใจเครื่องหมายอัญประกาศคู่ (") ดังนั้นการสืบค้นของคุณควรปราศจากเครื่องหมายอัญประกาศคู่ (") และควรใช้เครื่องหมายคำพูดเดี่ยว (') เท่านั้น
Back-trip (`) เป็นทางเลือกที่จะใช้ใน SQL และใช้สำหรับชื่อตารางชื่อฐานข้อมูลและชื่อคอลัมน์
หากคุณกำลังพยายามเขียนคำค้นหาในส่วนหลังของคุณเพื่อเรียก 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\'';
ปัญหาเกี่ยวกับเครื่องหมายคำพูดคู่ (") หรือเดี่ยว (') เกิดขึ้นเมื่อเราต้องกำหนดค่าไดนามิกบางค่าและดำเนินการต่อสตริงเช่น:
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