这是我的原始程序,效果很好:
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 Developer 在下面给了我一条弯曲的红线,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"
(或什至a1
)是只有计算机才能想到的那种表别名。使用表名的某种缩写形式的别名会好得多,也许在这种情况下c
。想象一下,如果您要加入六张桌子 - 现在是哪一张a3
?哦,对了,就是ORDER_DETAILS
。(虽然在这种情况下,表名很短,没有必要给它起别名。)所以,会好得多
(我也会小写它,因为这不是 1974 年,我的编辑器使用颜色和粗体突出显示语言关键字,但我们会放手。)
硬编码模式名称是不好的做法,因为它充其量是多余的(对象在您已经在使用的模式中,因此除了不必要的复杂性之外它不会增加任何内容)或更糟糕的是,它会限制可移植性(如果您曾经重命名模式或移动您的代码)必须通过它清理硬编码的引用)。
我确信这是一个很好的聪明功能,但在这种情况下,这不是一个好的建议。
A1
是表的别名"C##ELLIE"."CPP"
过程是相同的,但是你和 oracle 也知道表 cpp 属于哪个模式。
另外,您还应该添加注释该程序的作用,如果您在 3 年后回来,则更容易知道您使用的架构以及它的用途
这是一个关于在对象名称周围使用双引号有什么问题的演示。仔细阅读每个命令并注意表名的大小写敏感,引用和不引用。
我可能会为您的代码推荐这个:
我们只使用一个表/视图,
cpp
所以别名不是绝对必要的,但如果将来另一个表添加到这个查询中会很有帮助。特别是对于 2+ 表查询,如果 SELECT 中的名称不是完全限定的(在列名之前提及表名或别名),那么如果将列添加到与另一个表中的另一列同名的表中,查询可能会中断桌子:
如果我们向地址添加一个状态列,上述查询将失败,因为它现在不明确。添加导致此类问题的列不会让数据库宣布“我添加了它,但顺便说一下,整个架构和依赖系统中的所有其他查询现在都将失败” - 你只需要找到那些通过测试失败的查询。或客户抱怨;)
如果我们完全限定它:
它会继续工作..
用列重复表名有点乏味和罗嗦。使用较短的名称不仅可以提高可读性..
..但在心理上提醒我们,我们可以出于不同的原因多次加入表:
总而言之,SQLDeveloper 正在尝试做一件好事,因为它正在朝着以下方面迈进:
它掉下来的地方是:
A1
,这无助于您记住任何东西;p
我选择人员和地址绝非偶然,我a
相信你会欣赏的。如果有一个派对和一个项目要加入,我可能会使用per
,pro
和par
. 我会避免pr
,因为 Person、Party 和 Project 在单词中都有p
和r
作为相关的初始辅音,所以pr
不要像使用三个字母那样明显地喊出“它是 PRoject 的别名”(但我当然会接受你的争论pe
,如果你想节省一些击键:)pa
)pr
builder.addcolumn( '"' || alias_name || '"."' || col_name || '",')
比检查列名并查看它是否需要要容易得多引用并仅在需要时添加它们。不幸的是,这意味着代码最终"
到处都是不可读的混乱......SELECT pErSon.NaME ...
很好;即使table.column只是PERSON。 NAME 不区分大小写。但是当我们盲目地添加引号时,我们绝对必须将名称全部大写,因为添加引号会使它们以区分大小写的方式处理!SELECT "pErSon"."NaME"
只是行不通,所以你仔细写出来,漂亮可读的*小写标识符不见了..SQLDeveloper 真的可以进行所有内省和逻辑来确定需要引用的内容,无论是因为时髦的字符、空格、大小写等。但它没有——它采用安全和简单的编码方法,比如“只是引用它”,“只是大写它”和“只是创建一个随机/增量独特的别名”,不幸的是,这是一个糟糕的建议,尽管它正在尝试的一些精神是一个好主意
*作为孩子,我们先学习小写字母;我们读小写句子的速度总是比大写的快