我是PLSQL的新手,所以我有一个非常基本的问题,我希望有人能帮助我。如果SQL语句是12g数据库,我想对11g DB运行一个直接的select语句,然后稍微修改该SQL语句的版本。结果应该输出到屏幕上。下面的代码可以工作,直到我添加SQL语句。我试过‘立即执行’,但这不起作用,然后使用游标-但对于多列和多行,这不可能是答案,因为它是长缠绕。我在这里错过了什么?这些语句可以是任何内容,例如:
--11g
select NAME,OPEN_MODE,DBID from v$database;
--12c
select NAME,OPEN_MODE,DBID,con_id from v$database;
我只想知道如何处理这样一个代码块中的任何SQL select语句(返回多行和多个cols)。谢谢。
DECLARE
v_dbver BINARY_INTEGER;
BEGIN
SELECT TO_NUMBER(SUBSTR(version,1,2)) INTO v_dbver FROM v$instance;
DBMS_OUTPUT.PUT_LINE('Version ='||v_dbver);
IF v_dbver < 12 THEN
DBMS_OUTPUT.PUT_LINE('Running against 11g');
ELSIF v_dbver >= 12 THEN
DBMS_OUTPUT.PUT_LINE('Running against 12c');
END IF;
END;
/
发布于 2021-06-23 17:39:16
编辑:请参阅底部的附加注释,了解如何使用管道函数来完成此操作。
ORACLE中的PL/SQL不像其他RDBMS那样返回数据集(就像Server一样,您可以在块或过程中的任何地方弹出一个随机的SELECT语句,它会将结果输出到网格中)。
Oracle将只作为标准的SELECT查询或通过一个refcursor输出到屏幕上。
你所做的被称为匿名块。匿名块不显示SELECT语句的结果。他们的存在是为了“完成工作”。我写了一篇博文,对此做了一些解释,欢迎大家来看看:https://sqldevdba.com/f/t-sql-vs-plsql-series-part-2-select-into
关于您的问题:您有几种选择,包括:
2.将结果写入表(使用Insert .,然后在完成时从该表中选择。(这是我在运行像报表这样的排定项目时首选的方法)。这也是最快的“走出家门”的方法,因为这样您就可以立即查询结果。
对于选项2(我可能会采取,但您当然不必这么做),它应该是这样的:
--If you have an existing table (TableName) that you always want to use
DECLARE
v_dbver BINARY_INTEGER;
BEGIN
SELECT TO_NUMBER(SUBSTR(version,1,2)) INTO v_dbver FROM v$instance;
DBMS_OUTPUT.PUT_LINE('Version ='||v_dbver);
--This table needs to exist already, so you'll have to have created it ahead of time
TRUNCATE TABLE TableNameHere; --Truncate the table to remove artifacts
IF v_dbver < 12 THEN
DBMS_OUTPUT.PUT_LINE('Running against 11g');
--11g
INSERT INTO TableName
(NAME,OPEN_MODE,DBID)
SELECT NAME,OPEN_MODE,DBID
FROM v$database;
ELSIF v_dbver >= 12 THEN
DBMS_OUTPUT.PUT_LINE('Running against 12c');
--12c
INSERT INTO TableName
(NAME,OPEN_MODE,DBID,con_id)
SELECT NAME,OPEN_MODE,DBID,con_id
FROM v$database;
END IF;
END;
--If you want it to DYNAMICALLY create the table:
DECLARE
v_dbver BINARY_INTEGER;
BEGIN
SELECT TO_NUMBER(SUBSTR(version,1,2)) INTO v_dbver FROM v$instance;
DBMS_OUTPUT.PUT_LINE('Version ='||v_dbver);
--This table needs to exist already, so you'll have to have created it ahead of time
TRUNCATE TABLE TableNameHere; --Truncate the table to remove artifacts
IF v_dbver < 12 THEN
DBMS_OUTPUT.PUT_LINE('Running against 11g');
--11g
CREATE TABLE TableName_Timestamp --This will auto-create the table
AS
SELECT NAME,OPEN_MODE,DBID
FROM v$database;
ELSIF v_dbver >= 12 THEN
DBMS_OUTPUT.PUT_LINE('Running against 12c');
--12c
CREATE TABLE TableName_Timestamp --This will auto-create the table
AS
SELECT NAME,OPEN_MODE,DBID,con_id
FROM v$database;
END IF;
END;
<#>EDIT!!好吧,我的世界被颠覆了。虽然这种方法并不完美,但它确实改变了一些事情。
此解决方案允许您设置和部署函数,并使该函数从SELECT语句返回数据集。试试看!!
发布于 2021-06-26 09:39:32
PL/SQL不是为编写查询而设计的,因此,正如其他人所提到的,您不能只使用select
并期望得到一个结果集。但是,根据您正在使用的客户端工具,您可能可以这样做:
declare
rc sys_refcursor;
begin
if dbms_db_version.ver_le_12 then open rc for
select name,open_mode,dbid from v$database;
else open rc for
'select name,open_mode,dbid,con_id from v$database';
end if;
dbms_sql.return_result(rc);
end;
通过快速测试,这可以在SQL*Plus (12c或更高版本)和中工作。它不适用于PL/SQL Developer 14.0.6。
请记住,如果您是针对11g运行的,v$database没有con_id
列,因此查询必须是动态的,以便进行编译。您甚至可以动态地构造一个完整的查询,而不是有两个查询。
编辑:现在我已经考虑过了,this无论如何也不能对11g运行,因为11g的dbms_sql
没有return_result
过程,对不起。但是,这种方法在不需要遗留数据库版本的其他情况下可能很有用。在12c之前,您可以使用var rc refcursor
定义一个refcursor变量,并在块完成后打印它(在SQL*Plus中工作,等等)。
https://dba.stackexchange.com/questions/294719
复制相似问题