使用EXECUTE IMMEDIATE选择数据并将其存储在变量中

时间:2018-06-26 05:47:14

标签: oracle stored-procedures plsql

我正在尝试选择一些行并将数据放入变量中。过程是

describe('Testing createTestExecutionForTestCases(testExecutionData)', () => {

    const testExecutionData = {
      info: {
        summary: 'summary',
      },
      tests: [{
        testKey: 'KEY-11',
        comment: 'failed',
        status: 'FAIL',
      }],
    };
    before(() => {

      const basePath = `${JIRAConfig.host}:${JIRAConfig.port}`;
      process.env.TOKEN = 'fake_token';
      const issueSearch = nock(basePath);
      issueSearch
        .post(`${JIRAConfig.testExecutionEndpoint}`, () => true).reply(200, {
          testExecIssue: {
            id: '11410',
            key: 'KEY-1',
            self: 'http://172.16.201.132:8080/rest/api/2/issue/11410',
          },
        })
        .post(`${JIRAConfig.testExecutionEndpoint}`, () => true).reply(404, {
          error: 'ERROR',
          errorMessage: 'Summary could not be empty',
        });

    });

    after(() => {

      nock.cleanAll();

    });

    it('Should create test execution issue in JIRA', async () => {

      await createTestExecutionForTestCases(testExecutionData);

      process.stdin.setEncoding('utf8');

      process.stdin.on('readable', () => {

        const chunk = process.stdin.read();
        if (chunk !== null) {

          expect(chunk).to.be.a('string');
          expect(chunk).to.equal('Test Execution created with ID KEY-1');

        }

      });

    });

    it('Should not create test execution issue if any of the mandatory is not present', async () => {

      await createTestExecutionForTestCases(testExecutionData);

      process.stdin.setEncoding('utf8');

      process.stdin.on('readable', () => {

        const chunk = process.stdin.read();
        if (chunk !== null) {

          expect(chunk).to.be.a('string');
          expect(chunk).to.equal('Unable to create Test Execution');

        }

      });

    });

  });

执行过程时,出现以下错误

CREATE OR REPLACE PROCEDURE GET_MESSAGE
AS
V_RESULT                VARCHAR2(2000);

begin


    EXECUTE IMMEDIATE 'SELECT MESSAGE_ID FROM MSG_TABLE WHERE ( DATE_OF_OPERATION BETWEEN 20180530 AND 20180622) AND (ROWNUM BETWEEN 1 and 2)' INTO V_RESULT;
        dbms_output.put_line('V_RESULT:'||V_RESULT);


end;
/

MSG_TABLE包含以下列和数据

Error starting at line : 37 in command -
BEGIN GET_MESSAGE; END;
Error report -
ORA-01422: exact fetch returns more than requested number of rows
ORA-06512: at "PG_DBO11.GET_MESSAGE", line 8
ORA-06512: at line 1
01422. 00000 -  "exact fetch returns more than requested number of rows"
*Cause:    The number specified in exact fetch is less than the rows returned.
*Action:   Rewrite the query or change number of rows requested

查询本身运行正常。我不知道如何将选定的行存储到变量中。我可能在这里错过了一件非常普通的事情。

2 个答案:

答案 0 :(得分:3)

您不需要动态SQL。该过程可以接受2个日期参数,并且可以直接在查询中使用。如果要在DBMS_OUTPUT中显示多行,一种简单的方法是使用隐式的for循环。

CREATE OR REPLACE PROCEDURE GET_MESSAGE( p_start_date date, p_end_date date)
AS

BEGIN

FOR rec IN 
(
    SELECT MESSAGE_ID FROM MSG_TABLE  
     WHERE  DATE_OF_OPERATION BETWEEN p_start_date AND p_end_date

 ) LOOP
        dbms_output.put_line('V_RESULT:'||rec.MESSAGE_ID);
   END LOOP;
END;
/

将过程称为

BEGIN 
 GET_MESSAGE(DATE '2018-05-30', DATE '2018-06-22'); 
END;
/

Demo

使用ROWNUM BETWEEN 1 and 2时您到底想做什么? 请注意,在子查询中仅使用ROWNUM而不使用ORDER BY并不能确保您可以看到前2个message_id。如果您还有其他要求,请通过编辑在问题中明确说明,我们可能会帮助您修改选择查询。

编辑:似乎可以使用XML输出,您应该选择dbms_xmlgen.getxml,它会为您提供CLOB的结果,可以从选择查询中选择结果。这是一个例子。

CREATE OR REPLACE FUNCTION pr_outxml RETURN CLOB
    AS
BEGIN
    RETURN dbms_xmlgen.getxml('select * from employees where rownum<= 2');
END;
/

现在,将输出作为select pr_outxml from dual;。您可以使用其他参数修改此代码。

答案 1 :(得分:0)

以下解决方案达到了我的目的。我已将V_RESULT用作XmlType ...

CREATE OR REPLACE PROCEDURE GET_MESSAGE
IS
V_RESULT                XMLTYPE;
V_QUERY                 VARCHAR(2000);
begin
V_QUERY:='SELECT
XMLELEMENT("root",XMLAGG(
                XMLELEMENT("data",
                        XMLELEMENT("MESSAGE_ID",MESSAGE_ID),
                        XMLELEMENT("MESSAGE",MESSAGE )

                        ))
                ) FROM MSG_TABLE WHERE (
DATE_OF_OPERATION BETWEEN 20180530 AND 20180622)  AND (ROWNUM BETWEEN 1 and 10)';
    EXECUTE IMMEDIATE  V_QUERY INTO V_RESULT;
    dbms_output.put_line('the result xml is '||v_result.getStringVal());
end;
/

这样,我可以选择多行,将其转换为xml并存储在一个变量中。