Mengapa pengembang SQL menyarankan format berbeda untuk prosedur yang berfungsi?
Ini adalah prosedur asli saya yang bekerja dengan baik:
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;
Tetapi Pengembang SQL memberi saya garis merah berlekuk-lekuk di bawah SELECT
dan menyarankan saya mengubahnya menjadi ini:
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;
Pertanyaan saya adalah (mengapa) ini lebih baik? Apa itu "A1"?
Jawaban
A1
adalah alias untuk tabel "C##ELLIE"."CPP"
prosedurnya sama, tetapi jadi Anda dan oracle tahu skema mana yang dimiliki tabel cpp juga.
Tambahan Anda juga harus menambahkan komentar apa prosedurnya, jika Anda kembali dalam 3 tahun lebih mudah untuk mengetahui, skema mana yang Anda gunakan dan untuk apa
Mengenai masalah mengapa ia menyarankan format yang berbeda ketika kode sudah berfungsi, tentu saja mungkin ada kode berformat buruk yang berfungsi, jadi pada prinsipnya tidak ada alasan mengapa Anda tidak mempertimbangkan perbaikan tata letak atau refactoring yang mungkin membuat kode lebih kuat, efisien, atau lebih mudah dikelola.
Namun, nama yang dikutip ganda adalah praktik yang buruk karena menyembunyikan kesalahan penamaan dan memaksa Anda untuk menentukan huruf besar / kecil, dan hasilnya kurang dapat dibaca daripada aslinya. Mereka benar-benar merupakan fitur portabilitas untuk digunakan dengan aplikasi pihak ketiga yang memiliki nama tabel yang aneh . Generator kode cenderung memberikan tanda kutip ganda pada segala hal karena lebih mudah melakukannya daripada mendeteksi apakah mereka benar-benar dibutuhkan dalam setiap kasus. Tidak mungkin begitu
from "C##ELLIE"."CPP" "A1"
adalah perbaikan apa pun
from cpp
kecuali mungkin untuk penggunaan alias tabel. Sebaiknya beri alias pada tabel (tanpa tanda kutip ganda!) Dan gunakan saat merujuk ke kolom. Tapi "A1"
(atau bahkan a1
) adalah jenis alias tabel yang hanya akan diimpikan oleh komputer. Akan jauh lebih baik menggunakan alias yang merupakan singkatan dari nama tabel, mungkin dalam kasus ini c
. Bayangkan jika Anda bergabung dengan enam tabel - sekarang yang mana a3
? Oh iya, itu ORDER_DETAILS
. (Meskipun dalam kasus ini nama tabelnya sangat pendek sehingga tidak ada gunanya mengaliasinya.) Jadi,
SELECT "A1"."CPP" "CPP"
FROM "C##ELLIE"."CPP" "A1"
akan jauh lebih baik sebagai adil
SELECT c.cpp
FROM cpp c
(Saya juga akan menggunakan huruf kecil karena ini bukan tahun 1974 dan editor saya menyoroti kata kunci bahasa menggunakan warna dan tebal, tetapi kami akan membiarkannya.)
Nama skema pengkodean keras adalah praktik yang buruk karena paling tidak mubazir (objek ada dalam skema yang sudah Anda kerjakan sehingga tidak menambahkan apa-apa kecuali komplikasi yang tidak perlu) atau lebih buruk lagi, membatasi portabilitas (jika Anda pernah mengganti nama skema atau memindahkan kode Anda ' harus melalui itu membersihkan referensi hardcode).
Saya yakin ini adalah fitur pintar yang berarti baik, tetapi dalam hal ini bukan saran yang baik.
Berikut adalah demo tentang apa yang salah dengan menggunakan tanda kutip ganda di sekitar nama objek. Baca setiap perintah dengan cermat dan perhatikan sensitivitas huruf dari nama tabel, dikutip dan tidak dikutip.
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
Saya mungkin akan merekomendasikan ini untuk kode Anda:
...
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);
...
Kami hanya menggunakan satu tabel / tampilan, cpp
jadi aliasing tidak sepenuhnya diperlukan, tetapi akan membantu jika di masa mendatang tabel lain ditambahkan ke kueri ini.
Khususnya dengan 2+ kueri tabel, jika nama di SELECT tidak sepenuhnya memenuhi syarat (sebutkan nama tabel atau alias sebelum nama kolom) maka kueri bisa rusak jika kolom ditambahkan ke tabel, yang memiliki nama yang sama dengan kolom lain di kolom lain. meja:
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
Jika kita menambahkan kolom Status ke Address, query di atas gagal karena sekarang ambigu. Menambahkan kolom yang menyebabkan masalah semacam ini tidak akan membuat DB mengumumkan "Saya menambahkannya, tetapi omong-omong, semua kueri lain di seluruh skema dan sistem dependen Anda sekarang akan gagal" - Anda hanya perlu mencari kueri yang gagal dengan pengujian. Atau pelanggan mengeluh;)
Jika kami sepenuhnya memenuhi syarat:
SELECT
person.name,
person.status,
address.street
FROM
person
INNER JOIN adress a ON person.addressid = address.id
Itu akan terus bekerja ..
Mengulangi nama tabel dengan kolom agak membosankan dan bertele-tele. Menggunakan nama yang lebih pendek tidak hanya meningkatkan keterbacaan ..
SELECT
p.name,
p.status,
a.street
FROM
person p
INNER JOIN address a ON p.addressid = a.id
..tapi secara psikologis mengingatkan kita bahwa kita dapat menggabungkan tabel dalam beberapa kali karena alasan yang berbeda:
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
Secara keseluruhan, SQLDeveloper mencoba melakukan hal yang baik di sini karena bergerak menuju pengertian yang baik tentang:
- Berikan tabel Anda alias yang masuk akal, dapat dibaca, dan relevan secara kontekstual
- Selalu isi nama kolom Anda dengan alias
Dimana jatuhnya adalah:
- Itu memilih nama alias omong kosong
A1
, yang tidak membantu Anda mengingat apa pun; Bukan kebetulan saya memilihp
orang dana
alamat, karena saya yakin Anda dapat menghargai. Jika ada Partai, dan Proyek untuk bergabung, saya mungkin menggunakanper
,pro
danpar
. Saya akan menghindaripr
karena Person, Party, dan Project semuanya memilikip
danr
sebagai konsonan awal yang relevan dalam kata tersebut, jadipr
jangan meneriakkan "ini adalah alias untuk Proyek" sejelas menggunakan tiga huruf (tapi saya pasti akan menerima Anda berdebat untukpe
,pa
danpr
jika Anda ingin menyimpan beberapa penekanan tombol :)) - Ini membabi buta menabrak tanda kutip ganda di mana-mana, mungkin "untuk keamanan" tetapi juga karena itu adalah jalur yang paling tidak resistan - Jauh lebih mudah untuk membuat kode logika menambahkan tanda kutip secara membabi buta
builder.addcolumn( '"' || alias_name || '"."' || col_name || '",')
daripada memeriksa nama kolom dan melihat apakah itu mungkin perlu mengutip dan hanya menambahkannya jika diperlukan. Sayangnya, ini berarti kode berakhir dengan kekacauan yang tidak terbaca di"
mana - mana .. - .. dan memulai dari itu "hanya kutipan membabi buta semuanya" adalah "dan kemudian membuat semua pengenal HURUF BESAR SEMUA, karena saat ini nama tabel / kolom tidak peka huruf besar-kecil.
SELECT pErSon.NaME ...
baik-baik saja; meskipun tabel.kolom hanya PERSON. NAMA bukan case sens .. Tetapi ketika kita menambahkan tanda kutip secara membabi buta, kita benar-benar harus meletakkan nama dalam huruf besar semua, karena menambahkan tanda kutip membuat mereka diperlakukan dengan cara yang peka huruf besar / kecil! TidakSELECT "pErSon"."NaME"
akan berhasil, jadi, pengenal huruf kecil Anda yang ditulis dengan cermat, dan huruf kecil * yang mudah dibaca hilang ..
SQLDeveloper benar-benar bisa masuk ke semua introspeksi dan logika untuk mencari tahu apa yang perlu dikutip, apakah itu karena karakter yang funky, spasi, case sens, dll. Tapi tidak - itu mengambil pendekatan kode yang aman dan sederhana seperti "just mengutipnya "," hanya huruf besar "dan" hanya membuat alias yang merupakan beberapa hal unik acak / tambahan "dan sayangnya itu adalah rekomendasi yang buruk, meskipun semangat dari beberapa dari apa yang dicoba adalah ide yang bagus
* sebagai anak-anak kita belajar huruf kecil sebelum huruf besar; kami selalu lebih cepat dalam membaca kalimat huruf kecil daripada huruf besar