เหตุใดผู้พัฒนา SQL จึงแนะนำรูปแบบอื่นสำหรับขั้นตอนที่ใช้งานได้
นี่คือขั้นตอนดั้งเดิมของฉันที่ทำงานได้อย่างสวยงาม:
create or replace PROCEDURE EXTRACT_0_CPP AS
CURSOR c_data IS
SELECT cpp,
rfu1,
rfu2,
mean_rfu,
charge_ph7_4,
hydropathy
FROM cpp
ORDER BY LENGTH(cpp);
F1 UTL_FILE.FILE_TYPE;
BEGIN
F1 := UTL_FILE.FOPEN( location => 'EXTRACT_DIR',
filename => '0_cpp.TXT',
open_mode => 'w',
max_linesize => 32767);
FOR cur_rec IN c_data LOOP
UTL_FILE.PUT_LINE (F1,
cur_rec.cpp || ':' ||
cur_rec.rfu1 || ':' ||
cur_rec.rfu2 || ':' ||
cur_rec.mean_rfu || ':' ||
cur_rec.charge_ph7_4 || ':' ||
cur_rec.hydropathy);
END LOOP;
UTL_FILE.FCLOSE(F1);
END;
แต่นักพัฒนา SQL ให้เส้นสีแดงด้านล่างSELECT
และแนะนำให้ฉันเปลี่ยนเป็นสิ่งนี้:
create or replace PROCEDURE EXTRACT_0_CPP AS
CURSOR c_data IS
SELECT
"A1"."CPP" "CPP",
"A1"."RFU1" "RFU1",
"A1"."RFU2" "RFU2",
"A1"."MEAN_RFU" "MEAN_RFU",
"A1"."CHARGE_PH7_4" "CHARGE_PH7_4",
"A1"."HYDROPATHY" "HYDROPATHY"
FROM
"C##ELLIE"."CPP" "A1"
ORDER BY
length("A1"."CPP");
F1 UTL_FILE.FILE_TYPE;
BEGIN
F1 := UTL_FILE.FOPEN( location => 'EXTRACT_DIR',
filename => '0_cpp.TXT',
open_mode => 'w',
max_linesize => 32767);
FOR cur_rec IN c_data LOOP
UTL_FILE.PUT_LINE (F1,
cur_rec.pk_cpp || ':' ||
cur_rec.rfu1 || ':' ||
cur_rec.rfu2 || ':' ||
cur_rec.mean_rfu || ':' ||
cur_rec.charge_ph7_4 || ':' ||
cur_rec.hydropathy);
END LOOP;
UTL_FILE.FCLOSE(F1);
END;
คำถามของฉันคือ (ทำไม) ถึงดีกว่านี้? "A1" คืออะไร?
คำตอบ
A1
เป็นนามแฝงของตาราง "C##ELLIE"."CPP"
ขั้นตอนเหมือนกัน แต่คุณและ oracle รู้ว่าสคีมาไหนที่ cpp เป็นของตารางด้วย
นอกจากนี้คุณควรเพิ่มความคิดเห็นว่าขั้นตอนนี้ทำอย่างไรหากคุณกลับมาใน 3 ปีจะง่ายกว่าที่จะรู้ว่าคุณใช้สคีมาใดและใช้ทำอะไร
ในเรื่องที่ว่าทำไมจึงแนะนำรูปแบบอื่นเมื่อโค้ดใช้งานได้แล้วแน่นอนว่าเป็นไปได้ที่จะมีโค้ดที่จัดรูปแบบไม่ดีซึ่งใช้งานได้ดังนั้นโดยหลักการแล้วไม่มีเหตุผลใดที่คุณไม่ควรพิจารณาการปรับปรุงเลย์เอาต์หรือการปรับโครงสร้างใหม่ที่อาจทำให้ รหัสที่แข็งแกร่งมีประสิทธิภาพหรือดูแลรักษาง่ายขึ้น
อย่างไรก็ตามชื่อที่ยกมาสองครั้งเป็นวิธีปฏิบัติที่ไม่ดีเนื่องจากซ่อนข้อผิดพลาดในการตั้งชื่อและบังคับให้คุณระบุตัวพิมพ์ใหญ่ / ตัวพิมพ์เล็กและผลลัพธ์จะอ่านได้น้อยกว่าต้นฉบับ พวกเขาเป็นจริงคุณลักษณะพกพาสำหรับใช้กับโปรแกรมของบุคคลที่สามที่มีชื่อตารางแปลก ตัวสร้างโค้ดมักจะตบเครื่องหมายคำพูดคู่รอบ ๆ ทุกสิ่งเพราะมันง่ายกว่าที่จะตรวจสอบว่าจำเป็นจริงหรือไม่ในแต่ละกรณี ไม่มีทางเป็นอย่างนั้น
from "C##ELLIE"."CPP" "A1"
เป็นการปรับปรุงประเภทใด ๆ
from cpp
ยกเว้นการใช้นามแฝงตาราง เป็นความคิดที่ดีที่จะตั้งนามแฝงให้กับตาราง (โดยไม่มีเครื่องหมายอัญประกาศคู่!) และใช้เมื่ออ้างถึงคอลัมน์ แต่"A1"
(หรือแม้แต่a1
) เป็นนามแฝงตารางที่มีเพียงคอมพิวเตอร์เท่านั้นที่จะฝันถึง มันจะดีกว่ามากถ้าใช้นามแฝงที่เป็นตัวย่อของชื่อตารางบางทีในกรณีc
นี้ ลองนึกดูว่าคุณรวมหกโต๊ะ - ตอนนี้คืออันa3
ไหน? โอ้ใช่ORDER_DETAILS
แล้ว (แม้ว่าในกรณีนี้ชื่อตารางจะสั้นมากจนไม่มีจุดนามแฝง) ดังนั้น
SELECT "A1"."CPP" "CPP"
FROM "C##ELLIE"."CPP" "A1"
จะดีกว่าที่เป็นเพียง
SELECT c.cpp
FROM cpp c
(ฉันจะใช้ตัวพิมพ์เล็กด้วยเพราะนี่ไม่ใช่ปี 1974 และตัวแก้ไขของฉันเน้นคำหลักภาษาโดยใช้สีและตัวหนา แต่เราจะปล่อยไป)
ชื่อสคีมาแบบฮาร์ดโค้ดเป็นแนวทางปฏิบัติที่ไม่ดีเนื่องจากซ้ำซ้อนมากที่สุด (อ็อบเจ็กต์อยู่ในสคีมาที่คุณใช้งานอยู่แล้วดังนั้นจึงไม่เพิ่มอะไรเลยนอกจากความซับซ้อนที่ไม่จำเป็น) หรือแย่กว่านั้นคือ จำกัด การพกพา (หากคุณเคยเปลี่ยนชื่อสคีมาหรือย้ายรหัสที่คุณ จะต้องผ่านการล้างข้อมูลอ้างอิงแบบฮาร์ดโค้ด)
ฉันแน่ใจว่านี่เป็นคุณสมบัติที่ชาญฉลาดที่มีความหมายดี แต่ในกรณีนี้มันไม่ใช่คำแนะนำที่ดี
นี่คือการสาธิตสิ่งผิดปกติในการใช้เครื่องหมายคำพูดคู่รอบชื่อวัตถุ อ่านคำสั่งแต่ละคำสั่งอย่างละเอียดและคำนึงถึงตัวพิมพ์เล็กและใหญ่ของชื่อตารางที่ยกมาและไม่ได้ยกมา
SQL> create table test_table_1 (dob date);
Table created.
SQL> create table "test_table_2" ("dob" date);
Table created.
SQL> select * from test_table_1;
no rows selected
SQL> select * from test_table_2;
select * from test_table_2
*
ERROR at line 1:
ORA-00942: table or view does not exist
SQL> select * from "test_table_2";
no rows selected
SQL>
SQL> select table_name
2 from user_tables
3 where upper(table_name) like 'TEST_TABLE%'
4 order by table_name;
TABLE_NAME
--------------------------------------------------------------------------------
TEST_TABLE_1
test_table_2
2 rows selected.
SQL>
SQL> drop table test_table_1;
Table dropped.
SQL> drop table test_table_2;
drop table test_table_2
*
ERROR at line 1:
ORA-00942: table or view does not exist
SQL> drop table "test_table_2";
Table dropped.
SQL> --
SQL> spo off
ฉันอาจให้คำแนะนำสำหรับรหัสของคุณ:
...
CURSOR c_data IS
SELECT c.cpp,
c.rfu1,
c.rfu2,
c.mean_rfu,
c.charge_ph7_4,
c.hydropathy
FROM cpp c
ORDER BY LENGTH(c.cpp);
...
เราใช้เพียงตาราง / มุมมองเดียวcpp
ดังนั้นการใช้นามแฝงจึงไม่จำเป็นอย่างยิ่ง แต่จะเป็นประโยชน์หากในอนาคตมีการเพิ่มตารางอื่นในแบบสอบถามนี้
โดยเฉพาะอย่างยิ่งกับคิวรีตารางมากกว่า 2 รายการหากชื่อใน SELECT ไม่ตรงตามคุณสมบัติทั้งหมด (ระบุชื่อตารางหรือนามแฝงก่อนชื่อคอลัมน์) การสืบค้นอาจแตกได้หากมีการเพิ่มคอลัมน์ลงในตารางซึ่งมีชื่อเดียวกันกับคอลัมน์อื่นในอีกคอลัมน์ ตาราง:
PersonTable: id, name, status, addressid
AddressTable id, street
--this is ok for now
SELECT name, status, street FROM person INNER JOIN street ON person.addressid = address.id
หากเราเพิ่มคอลัมน์สถานะในที่อยู่ข้อความค้นหาข้างต้นจะล้มเหลวเนื่องจากตอนนี้ยังไม่ชัดเจน การเพิ่มคอลัมน์ที่ทำให้เกิดปัญหาแบบนี้จะไม่ทำให้ DB ประกาศว่า "ฉันได้เพิ่มเข้าไปแล้ว แต่อย่างไรก็ตามการค้นหาอื่น ๆ ในสคีมาและระบบที่เกี่ยวข้องของคุณจะล้มเหลวในขณะนี้" - คุณจะต้องค้นหา แบบสอบถามที่ล้มเหลวโดยการทดสอบ หรือลูกค้าบ่น;)
หากเรามีคุณสมบัติครบถ้วน:
SELECT
person.name,
person.status,
address.street
FROM
person
INNER JOIN adress a ON person.addressid = address.id
มันคงทำงาน ..
การใช้ชื่อตารางซ้ำกับคอลัมน์เป็นเรื่องที่น่าเบื่อและยุ่งยากเล็กน้อย การใช้ชื่อที่สั้นลงไม่เพียง แต่ช่วยเพิ่มความสามารถในการอ่าน ..
SELECT
p.name,
p.status,
a.street
FROM
person p
INNER JOIN address a ON p.addressid = a.id
.. แต่ในทางจิตวิทยาเตือนเราว่าเราสามารถเข้าร่วมโต๊ะได้หลายครั้งด้วยเหตุผลที่แตกต่างกัน:
SELECT
p.name,
p.status,
a_work.street as workstreet,
a_home.street as homestreet
FROM
person p
INNER JOIN address a_work ON p.work_addressid = a.id --note, i've silently upgraded Person here to track two addresses
INNER JOIN address a_home ON p.home_addressid = a.id
โดยสรุปแล้ว SQLDeveloper พยายามที่จะทำสิ่งที่ดีที่นี่เพื่อที่จะก้าวไปสู่ความรู้สึกที่ดีของ:
- ให้ตารางของคุณมีนามแฝงที่เหมาะสมอ่านง่ายและเกี่ยวข้องกับบริบท
- กำหนดชื่อคอลัมน์ของคุณให้ครบถ้วนด้วยนามแฝงเสมอ
จุดที่ตกลงมาคือ:
- การเลือกชื่อนามแฝงไร้สาระ
A1
ซึ่งไม่ได้ช่วยให้คุณจำอะไรได้เลย ไม่ใช่เรื่องบังเอิญที่ฉันเลือกp
บุคคลและที่a
อยู่เพราะฉันมั่นใจว่าคุณจะประทับใจ ถ้ามีงานเลี้ยงและโครงการที่จะเข้าร่วมในฉันอาจใช้per
, และpro
par
ฉันต้องการหลีกเลี่ยงpr
เพราะคนพรรคและโครงการทั้งหมดมีp
และr
เป็นพยัญชนะเริ่มต้นที่เกี่ยวข้องในคำจึงpr
ไม่ได้ตะโกน "มันเป็นนามแฝงสำหรับโครงการ" ตามที่เห็นได้ชัดว่าการใช้ตัวอักษรสามตัวไม่ ( แต่แน่นอนฉันจะยอมรับคุณเถียงpe
,pa
และpr
หากคุณต้องการบันทึกการกดแป้นพิมพ์ไม่กี่ครั้ง :)) - การใส่เครื่องหมายอัญประกาศแบบสุ่มสี่สุ่มห้าในทุกหนทุกแห่งอาจเป็น "เพื่อความปลอดภัย" แต่ยังเป็นเพราะเส้นทางของการต่อต้านน้อยที่สุด - ง่ายกว่ามากในการเขียนรหัสตรรกะของการเพิ่มเครื่องหมายคำพูดแบบสุ่มสี่สุ่มห้าเช่น
builder.addcolumn( '"' || alias_name || '"."' || col_name || '",')
ตรวจสอบชื่อคอลัมน์และดูว่าอาจต้องใช้หรือไม่ อ้างและเพิ่มหากจำเป็นเท่านั้น น่าเสียดายที่หมายความว่าโค้ดจบลงด้วยความยุ่งเหยิงที่ไม่สามารถอ่านได้"
ทุกที่ .. - .. และเป็นผู้นำต่อไปจากที่ "เพียงสุ่มสี่สุ่มห้าพูดทุกอย่าง" เป็น "และแล้วทำให้ทุกตัวระบุตัวพิมพ์ใหญ่ทั้งหมดเพราะตอนนี้ตาราง / ชื่อคอลัมน์ที่มีไม่ได้กรณีที่สำคัญ.
SELECT pErSon.NaME ...
จะปรับ; แม้ว่า table.column เป็นเพียง PERSON ชื่อมันไม่ได้เป็นกรณี Sens .. แต่เมื่อเราได้เพิ่มคำพูดสุ่มสี่สุ่มห้าเราแล้วอย่างต้องใส่ชื่อในตัวพิมพ์ใหญ่ทั้งหมดเนื่องจากการเพิ่มคำพูดที่ทำให้พวกเขาได้รับการปฏิบัติในทางที่มีความละเอียดอ่อนกรณี!SELECT "pErSon"."NaME"
ก็จะไม่ทำงาน ดังนั้นตัวระบุตัวพิมพ์เล็ก * ที่อ่านได้อย่างสวยงามของคุณจึงหายไป ..
SQLDeveloper สามารถไปที่การวิปัสสนาและตรรกะทั้งหมดในการหาสิ่งที่จำเป็นต้องยกมาไม่ว่าจะเป็นเพราะอักขระขี้ขลาดช่องว่างความรู้สึกของตัวพิมพ์และอื่น ๆ แต่ก็ไม่ได้ - การใช้วิธีโค้ดที่ปลอดภัยและเรียบง่าย อ้างว่า "," เพียงตัวพิมพ์ใหญ่ "และ" เพียงสร้างนามแฝงที่เป็นสิ่งที่ไม่ซ้ำกันแบบสุ่ม / เพิ่มขึ้น "และนั่นเป็นคำแนะนำที่ไม่ดีแม้ว่าจิตวิญญาณของสิ่งที่พยายามจะเป็นความคิดที่ดี
* ตอนเด็ก ๆ เราเรียนตัวพิมพ์เล็กก่อนตัวพิมพ์ใหญ่ เราอ่านประโยคตัวพิมพ์เล็กได้เร็วกว่าประโยคตัวพิมพ์ใหญ่เสมอ