¿Por qué el desarrollador de SQL sugiere un formato diferente para un procedimiento que funciona?
Este es mi procedimiento original que funciona maravillosamente:
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;
Pero SQL Developer me da una línea roja ondulada debajo SELECT
y sugiere que la cambie a esto:
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;
Mi pregunta es (¿por qué) esto es mejor? ¿Qué es "A1"?
Respuestas
A1
es el alias de la tabla "C##ELLIE"."CPP"
El procedimiento es el mismo, pero usted y Oracle también saben a qué esquema pertenece la tabla cpp.
Adicional también debes agregar un comentario de lo que hace el procedimiento, si vuelves en 3 años es más sencillo saber, qué esquema usaste y para qué sirve
Sobre el tema de por qué sugeriría un formato diferente cuando el código ya funciona, por supuesto que es posible tener un código mal formateado que funcione, por lo que, en principio, no hay razón por la que no debería considerar las mejoras de diseño o refactorización que podrían hacer que el código más robusto, eficiente o más fácil de mantener.
Sin embargo, los nombres entre comillas dobles son una mala práctica porque ocultan errores de nomenclatura y lo obligan a especificar mayúsculas / minúsculas, y el resultado es menos legible que el original. Realmente son una característica de portabilidad para usar con aplicaciones de terceros que tienen nombres de tablas extraños . Los generadores de código tienden a colocar comillas dobles alrededor de todo porque es más fácil hacer eso que detectar si realmente son necesarios en cada caso. No hay manera de que
from "C##ELLIE"."CPP" "A1"
hay algún tipo de mejora en
from cpp
excepto quizás por el uso de un alias de tabla. Es una buena idea darle a la tabla un alias (¡sin comillas dobles!) Y usarlo cuando se refiera a columnas. Pero "A1"
(o incluso a1
) es el tipo de alias de tabla que solo una computadora soñaría. Sería mucho mejor usar un alias que sea una especie de abreviatura del nombre de la tabla, quizás en este caso c
. Imagínese si estuviera uniendo seis mesas, ¿ahora cuál es a3
? Oh cierto, eso es ORDER_DETAILS
. (Aunque en este caso el nombre de la tabla es tan corto que no tiene sentido ponerle un alias).
SELECT "A1"."CPP" "CPP"
FROM "C##ELLIE"."CPP" "A1"
sería mucho mejor como solo
SELECT c.cpp
FROM cpp c
(También lo pondría en minúsculas porque esto no es 1974 y mi editor resalta las palabras clave del idioma usando colores y negrita, pero lo dejaremos pasar).
Codificar nombres de esquemas es una mala práctica porque, en el mejor de los casos, es redundante (el objeto está en el esquema en el que ya está trabajando, por lo que no agrega nada excepto una complicación innecesaria) o, lo que es peor, limita la portabilidad (si alguna vez cambia el nombre del esquema o mueve el código usted ' Tendré que revisarlo limpiando las referencias codificadas).
Estoy seguro de que esta es una función inteligente que tiene buenas intenciones, pero en este caso no es un buen consejo.
Aquí hay una demostración de lo que está mal con el uso de comillas dobles en los nombres de los objetos. Lea cada comando con atención y preste atención a la distinción entre mayúsculas y minúsculas de los nombres de las tablas, entre comillas y sin comillas.
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
Probablemente haría una recomendación de esto para su código:
...
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);
...
Solo estamos usando una tabla / vista, cpp
por lo que el alias no es estrictamente necesario, pero sería útil si en el futuro se agregara otra tabla a esta consulta.
Particularmente con 2+ consultas de tabla, si los nombres en SELECT no están completamente calificados (mencione un nombre de tabla o alias antes del nombre de columna), las consultas pueden romperse si se agregan columnas a tablas, que tienen el mismo nombre que otra columna en otra mesa:
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
Si agregamos una columna de Estado a la Dirección, la consulta anterior falla porque ahora es ambigua. Agregar una columna que causa este tipo de problema no hará que la base de datos anuncie "Lo agregué, pero por cierto, todas estas otras consultas en su esquema y sistemas dependientes ahora fallarán"; solo tendrá que encontrar las consultas que fallan mediante la prueba. O clientes quejándose;)
Si lo calificamos completamente:
SELECT
person.name,
person.status,
address.street
FROM
person
INNER JOIN adress a ON person.addressid = address.id
Seguiría funcionando ...
Repetir el nombre de la tabla con las columnas es un poco tedioso y prolijo. Usar un nombre más corto no solo mejora la legibilidad.
SELECT
p.name,
p.status,
a.street
FROM
person p
INNER JOIN address a ON p.addressid = a.id
... pero psicológicamente nos recuerda que podemos unir tablas en varias ocasiones por diferentes razones:
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
En resumen, SQLDeveloper está tratando de hacer algo bueno aquí, ya que se está moviendo hacia el buen sentido de:
- Dé a sus tablas un alias sensible, legible y contextualmente relevante
- Siempre califique completamente los nombres de sus columnas con el alias
Donde se cae es:
- Es elegir un nombre de alias de mierda
A1
, que no te ayuda a recordar nada; No es casualidad que haya elegidop
por persona ya
por dirección, como estoy seguro de que podrá apreciar. Si había un partido, y un proyecto para unirse puede ser que utiliceper
,pro
ypar
. Me evitarpr
debido a persona, Partido y todos tienen Proyectop
yr
como consonantes iniciales relevantes de la palabra, por lo quepr
no grita "es un alias para el proyecto", como, obviamente, como el uso de tres letras hace (pero ciertamente aceptaría que argumentar a favorpe
,pa
ypr
si desea guardar algunas pulsaciones de teclas :)) - Está metiendo comillas dobles ciegamente en todas partes, probablemente "por seguridad", pero también porque es el camino de menor resistencia. Es mucho más fácil codificar una lógica de agregar comillas ciegamente como
builder.addcolumn( '"' || alias_name || '"."' || col_name || '",')
lo es inspeccionar el nombre de una columna y ver si podría necesitar citando y solo agréguelos si es necesario. Desafortunadamente, esto significa que el código termina siendo un desastre ilegible en"
todas partes ... - .. y a partir de ese "simplemente cite ciegamente todo" es "y luego haga que todos los identificadores sean TODOS EN MAYÚSCULAS , porque en este momento los nombres de tabla / columna no distinguen entre mayúsculas y minúsculas.
SELECT pErSon.NaME ...
está bien; aunque la columna de tabla es solo PERSONA. NOMBRE no es sens caso .. Pero cuando hemos añadido citas a ciegas, entonces tenemos absolutamente a poner los nombres en mayúsculas, debido a la adición de las cotizaciones de los hace ser tratados de una manera sensible caso!SELECT "pErSon"."NaME"
no va a funcionar, por lo que sus identificadores en minúsculas cuidadosamente escritos y maravillosamente legibles * se han ido
SQLDeveloper realmente podría ir a toda esa introspección y lógica de resolver lo que se necesita citar, ya sea por caracteres extravagantes, espacios, mayúsculas y minúsculas, etc. cítelo "," solo ponlo en mayúsculas "y" solo crea un alias que sea algo único aleatorio / incremental "y esa es, desafortunadamente, una mala recomendación, aunque el espíritu de algo de lo que está intentando es una buena idea
* de niños aprendemos minúsculas antes que mayúsculas; siempre somos más rápidos para leer oraciones en minúsculas que en mayúsculas