Plsql 关于DECLARE块包含注释动态输入变量的问题
我刚刚接触PL/SQL 我写了一个块来计算圆的半径和周长,如下所示:Plsql 关于DECLARE块包含注释动态输入变量的问题,plsql,oracle11g,oracle-sqldeveloper,sqlplus,Plsql,Oracle11g,Oracle Sqldeveloper,Sqlplus,我刚刚接触PL/SQL 我写了一个块来计算圆的半径和周长,如下所示: SET SERVEROUTPUT ON; CREATE OR REPLACE PROCEDURE cal_circle AS -- DECLARE pi CONSTANT NUMBER := 3.1415926; radius NUMBER := 3; -- to make it more dynamic I can set -- radius NUMBER
SET SERVEROUTPUT ON;
CREATE OR REPLACE PROCEDURE cal_circle AS
-- DECLARE
pi CONSTANT NUMBER := 3.1415926;
radius NUMBER := 3;
-- to make it more dynamic I can set
-- radius NUMBER := &enter_value;
circumference DECIMAL(4,2) := radius * pi * 2;
area DECIMAL(4,2) := pi * radius ** 2;
BEGIN
-- DBMS_OUTPUT.PUT_LINE('Enter a valur of radius: '|| radius);
dbms_output.put_line('For a circle with radius '
|| radius
|| ',the circumference is '
|| circumference
|| ' and the area is '
|| area
|| '.');
END;
/
在这里,您可以看到我已经注释了声明代码半径编号:=&enter_值但是,当我在SQL*Plus或SQL Developer中运行脚本时,总会收到弹出消息,如请输入enter\u value
的值
相反,如果我在declare中删除这个注释并将其放在它的外部,那么将不再有提示
SET SERVEROUTPUT ON;
/* to make it more dynamic, I can set
radius NUMBER := &enter_value;
*/
CREATE OR REPLACE PROCEDURE cal_circle AS
-- DECLARE
pi CONSTANT NUMBER := 3.1415926;
radius NUMBER := 3;
circumference DECIMAL(4,2) := radius * pi * 2;
area DECIMAL(4,2) := pi * radius ** 2;
BEGIN
......
这里我想澄清的是,当我试图注释一个动态变量时,这是否意味着DECLARE块不能接受注释
谢谢。您可以使用参数而不是替换变量来允许不同的用户使用不同的pi值调用过程
为此,我建议使用函数
而不是过程
,但这里有一个示例(也使用半径
的参数):
然后尝试一下:
BEGIN
CAL_CIRCLE(3, 3.14);
END;
/
For a circle with radius 3,the circumference is 18.84 and the area is
28.26.Calculated with Pi=: 3.14
BEGIN
CAL_CIRCLE(3, 3.14159);
END;
/
For a circle with radius 3,the circumference is 18.85 and the area is
28.27.Calculated with Pi=: 3.14159
如果您确实需要编译过程,并使用替换值pi为其常数(不推荐)设置不同的值,则可以首先使用定义设置替换变量。如定义pi_值=3.1415代码>,然后稍后使用和pi_值
Update:为什么SQLPlus和sqldeveloper会检测到替换变量
,并为其请求一个值,即使它在注释中也是如此
TLDR:SQL客户端必须向服务器发送注释。预处理注释中的替换提供了更大的灵活性,并使SQL客户机更简单。客户对控制替代行为有很好的支持。在最终确定的代码中没有太多理由使用孤立替代变量
较长版本:
这些工具都是数据库客户机——它们有很多特性,但最重要的是,它们的第一项工作是收集输入SQL,将其传递到数据库服务器,并处理获取的数据
Comment
s需要连同其附带的SQL
语句一起发送到数据库服务器。这是有原因的——因此用户可以在数据库中保存他们编译的SQL
代码的注释,当然也可以保存编译器提示的注释
替换变量
不会像注释一样随SQL一起传递到服务器。而是首先对它们求值,并将结果SQLText
发送到服务器。(您可以看到进入服务器的SQL
将其替换变量
替换为实际值。请参见V$SQLTEXT
)
由于服务器“利用”了注释,因此它使事情更加灵活,并简化了SQLPlus
的工作,以替换注释中的替换变量。(如果需要,这可以被覆盖。我将在下面展示)SQLPlus
、SQLDeveloper
等可能被设计为忽略注释中的替换变量,但这会降低它们的灵活性,可能需要更多的代码,因为它们需要识别注释并相应地逐行更改其行为。下面我将进一步展示这种灵活性的一些示例
以这种方式工作的工具没有什么缺点。
假设一个人只想在开发过程中忽略一段代码,然后快速运行所有代码。如果一个人有DEFINE
所有东西,即使它没有被使用,或者删除所有注释过的代码,只是为了让它可以运行,这将是一件很烦人的事情。因此,这些工具允许您设置DEFINE OFF编码>并忽略变量
例如,这运行良好:
SET DEFINE OFF;
--SELECT '&MY_FIRST_IGNORED_VAR' FROM DUAL;
-- SELECT '&MY_SECOND_IGNORED_VAR' FROM DUAL;
SELECT 1919 FROM DUAL;
如果需要在查询中使用&
本身,SQLPlus
允许您选择另一个字符作为替换标记。控制事情有很多选择
如果一个人已经完成了自己的最终查询
或过程
,那么使用未定义替换的剩余“孤立”注释是无效的。开发完成后,应删除所有孤立替换,剩余的任何内容都应引用有效的DEFINE
d变量
下面是一个在注释中使用处理substitution
s的示例。
假设您想调优一些性能较差的SQL
。您可以在HINT
s(注释中)中使用替换变量,以允许快速更改使用的索引或执行模式等,而无需实际更改查询脚本
CREATE TABLE TEST_TABLE_1(TEST_KEY NUMBER PRIMARY KEY,
TEST_VALUE VARCHAR2(128) NOT NULL,
CONSTRAINT TEST_VALUE_UNQ UNIQUE (TEST_VALUE));
INSERT INTO TEST_TABLE
SELECT LEVEL, 'VALUE-'||LEVEL
FROM DUAL CONNECT BY LEVEL <= 5000;
X平面图:
------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 66 | 1 (0)| 00:00:01 |
|* 1 | INDEX UNIQUE SCAN| TEST_VALUE_UNQ | 1 | 66 | 1 (0)| 00:00:01 |
------------------------------------------------------------------------------------
但可以通过提示强制进行完全扫描。通过在提示(注释)中使用替换变量,可以允许替换变量的值指导查询执行:
DEFINE V_WHICH_FULL_SCAN = 'TEST_TABLE';
SELECT /*+ FULL(&V_WHICH_FULL_SCAN) */ TEST_VALUE FROM TEST_TABLE WHERE TEST_VALUE = 'VALUE-1919';
此处,替换变量(在其注释中)已更改查询执行
X平面图:
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 23 | 1518 | 9 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| TEST_TABLE | 23 | 1518 | 9 (0)| 00:00:01 |
--------------------------------------------------------------------------------
如果这里有一堆表,而不是一个表,那么一个人可以定义不同的目标进行全面扫描,并快速评估每个对查询的影响。您可以使用参数而不是替换变量,以允许不同的用户使用不同的pi值调用过程
为此,我建议使用函数
而不是过程
,但这里有一个示例(也使用半径
的参数):
然后尝试一下:
BEGIN
CAL_CIRCLE(3, 3.14);
END;
/
For a circle with radius 3,the circumference is 18.84 and the area is
28.26.Calculated with Pi=: 3.14
BEGIN
CAL_CIRCLE(3, 3.14159);
END;
/
For a circle with radius 3,the circumference is 18.85 and the area is
28.27.Calculated with Pi=: 3.14159
如果您确实需要编译过程,并使用替换值pi为其常数(不推荐)设置不同的值,则可以首先使用定义设置替换变量。如定义pi_值=3.1415代码>,然后使用和pi_值
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 23 | 1518 | 9 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| TEST_TABLE | 23 | 1518 | 9 (0)| 00:00:01 |
--------------------------------------------------------------------------------