2017-10-01 1 views
0

저는 PL/SQL을 처음 접했습니다. 내 스크립트를 실행할 때, 당신은 내가하지만, 가 선언 코드 radius NUMBER := &enter_value; 논평했습니다 것을 볼 수 있었다 여기DECLARE 블록에 대한 문제는 주석 처리 된 동적 입력 변수를 포함합니다.

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; 
/

:

나는 다음과 같은 원의 반지름과 둘레를 계산하기 위해 블록을 썼다 SQL * Plus 또는 SQL Developer에서 항상 please enter the value for enter_value과 같은 팝업 메시지가 나타납니다.

반대의 경우, 선언문에서이 주석을 삭제하고 그냥 그 문장 밖으로 넣으면 더 이상 프롬프트가 표시되지 않습니다.

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 블록이 의견을 받아 들일 수 없습니다 의미합니까 명확히하려면?

감사합니다.

+0

감사합니다. rz.He. 스크립트를 실행하기 전에 먼저 DEFINE enter_value = 3.1415;와 같은 것을 호출해야합니까? 대체 변수를 사용하려면 먼저 변수를 정의해야합니다. 그렇지 않으면 프롬프트가 표시됩니다. – alexgibbs

+0

또한 익명 블록 대신 프로 시저를 컴파일하기 때문에 pi에 대한 매개 변수 사용을 고려했는지 궁금합니다. (프로 시저의 모든 후속 용도에 영향을 미칠 수있는) 프로 시저를 다시 컴파일하는 대신 다른 사용자가 다른 값의 pi를 사용하도록 허용 할 수 있습니까? – alexgibbs

+0

니스. pi에 대한 값이 다르면 코드가 다른 기본 기하학을 가진 대체 유니버스에서 다시 사용할 수 있습니다. 더 큰 그림을 생각해보십시오. –

답변

4

대체 변수 대신 매개 변수를 사용하여 다른 사용자가 다른 pi 값으로 프로 시저를 호출 할 수 있습니다.

이 경우 PROCEDURE 대신 FUNCTION을 사용하는 것이 좋지만 여기에 예제가 있습니다 (또한 radius에 대한 매개 변수 사용). :

CREATE OR REPLACE PROCEDURE CAL_CIRCLE(P_RADIUS IN NUMBER, P_PI IN NUMBER) AS 
    CIRCUMFERENCE DECIMAL(4, 2) := P_RADIUS * P_PI * 2; 
    AREA   DECIMAL(4, 2) := P_PI * P_RADIUS ** 2; 

    BEGIN 

    DBMS_OUTPUT.put_line('For a circle with radius ' 
         || P_RADIUS 
         || ',the circumference is ' 
         || CIRCUMFERENCE 
         || ' and the area is ' 
         || AREA 
         || '.' || 'Calculated with Pi=: ' || P_PI); 
    END; 
/

그런 다음 그것을 밖으로 시도 :

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 

당신이 정말로 실제로 COMPILE 파이의 치환 값과의 상수 (권장하지 않음)에 대해 다른 값과 절차, 당신은을 설정할 수 있습니다해야하는 경우 첫 번째 대체 변수는 DEFINE입니다. DEFINE pi_value = 3.1415;과 같고 나중에 &pi_value을 사용합니다.

업데이트 : 그것은 코멘트에있는 경우에도 왜, SQLPLUSSQL 개발자Substitution Variable를 감지하고 그 값을 요청합니까?

TLDR : SQL 클라이언트는 서버에 설명을 제공해야합니다. 주석의 사전 처리 대체는 유연성을 높이고 SQL 클라이언트를 더 간단하게 유지합니다. 클라이언트는 대체 동작을 제어하기위한 좋은 지원을합니다. 최종 코드에서 고아 대체 변수를 갖는 이유는별로 없습니다.

긴-버전 : 이 도구는 데이터베이스 클라이언트 - 그들은 먼저 기능을 많이하지만이 무엇보다도 자신의 첫 번째 작업은 입력 SQL을 수집 데이터베이스 서버에 전달하고 가져온 데이터를 처리하는 것입니다.

CommentSQL 문과 함께 데이터베이스 서버에 전달되어야합니다. 여기에는 이유가 있습니다. 따라서 사용자는 컴파일 된 SQL 코드를 데이터베이스에 저장할 수 있지만 compiler hint에도 주석을 저장할 수 있습니다.

Substitution Variables SQL과 함께 서버에 주석이 제공되지 않습니다. 대신 그들은 첫 번째으로 평가되고 결과는 SQLText입니다. 서버에 들어간 SQLSubstitution Variables이 실제 값으로 바뀌 었음을 알 수 있습니다 (V$SQLTEXT 참조).

서버가 주석을 "사용"하기 때문에보다 유연하게 만들 수 있으며 SQLPlus이 주석에서 대체 변수를 대체하는 작업을 단순화합니다. (필요한 경우이를 재정의 할 수 있습니다. 아래에서 설명하겠습니다). SQLPlus, SQLDeveloper은 주석의 대체 변수를 무시하도록 설계되었지만 주석을 인식하고 그에 따라 동작을 변경해야하기 때문에 코드가 덜 유연하고 더 많은 코드가 필요할 수 있습니다. . 아래에서이 유연성에 대한 몇 가지 예를 보여 드리겠습니다.

이러한 방식으로 작동하는 도구에는 많은 단점이 없습니다.

개발하는 동안 잠깐 코드 덩어리를 무시하고 신속하게 모든 것을 실행하려고한다고 가정합니다. 누구도 DEFINE을 사용하지 않았거나 주석이 달린 코드를 모두 삭제해도 문제는 없습니다. 따라서이 도구 대신 SET DEFINE OFF;을 허용하고 변수를 무시하십시오.

예를 들어,이 잘 실행 :

SET DEFINE OFF; 
--SELECT '&MY_FIRST_IGNORED_VAR' FROM DUAL; 
-- SELECT '&MY_SECOND_IGNORED_VAR' FROM DUAL; 
SELECT 1919 FROM DUAL; 

하나가 쿼리에서 '&' 자체를 사용할 필요가있는 경우, SQLPlus 당신이 대체 마커와 같은 다른 문자를 선택할 수 있습니다. 사물을 제어 할 수있는 옵션이 많이 있습니다.

최종본 인 query 또는 procedure의 개발이 끝나면 정의되지 않은 대체가 포함 된 "고아"의견을 남겨 두는 것은 유효한 상황이 아닙니다. 개발이 완료되면 고아 대체가 모두 제거되어야하고 나머지는 유효한 DEFINE 개의 변수를 참조해야합니다.

다음은 댓글에서 처리 substitution을 사용하는 예입니다. 성능이 좋지 않은 일부 조정하려는 경우 SQL. HINT (대체로)에있는 대체 변수를 사용하면 실제로 쿼리 스크립트를 변경하지 않고도 어떤 인덱스가 사용되었는지, 실행 모드인지 등을 신속하게 변경할 수 있습니다.

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; 

일반적으로 보통의 UNIQUE INDEX 가져 오는 데이터를 사용하는 것이 여기 TEST_VALUE에 대해 predicating 쿼리.

SELECT TEST_VALUE FROM TEST_TABLE WHERE TEST_VALUE = 'VALUE-1919'; 

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 | 
-------------------------------------------------------------------------------- 

, 사람이 빠르게 쿼리에 각각 영향을 DEFINE 다른 풀 스캔을 목표 등을 평가할 수있다.

+0

안녕하세요 @alexgibbs, 답장을 보내 주셔서 감사합니다. 귀하의 제안은 훌륭합니다! 괜찮 으면 * DECLARE 블록이 주석 & 변수 *를 실행하려고하는 이유에 대해 조금 더 설명해 주시겠습니까? (필자는 평범한 텍스트에 주석을 달고 괜찮을 것입니다.) * 어떤 특기 사항이 있습니까 현장 뒤에서 *? –

+0

감사합니다. rz.He 확실합니다. 나는 약 1 시간 동안 나의 책상에서 멀리 있고 그러나 그 때 철저히 구명 할 것이다. 감사합니다 – alexgibbs

+0

감사합니다 @alexgibbs, 나는 그것을 기다리고 있습니다, 그것을 기대, p –

관련 문제