从命令提示符编译 PLSQL(不在 sqlplus 内)

发布于 2024-09-13 19:56:41 字数 112 浏览 4 评论 0原文

有没有什么方法可以从命令提示符编译 plsql,而不是打开 sqlplus 并写入命令或@文件名?

我们希望将输出导入到文件中并解析它以使用我们正在开发的代码审查工具

谢谢...

is there any way compiling plsql from command prompt not by opening sqlplus and writing the command or @filename?

We want to import the output to a file and parse it for a code review tool we are working on

Thanks...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

诗化ㄋ丶相逢 2024-09-20 19:56:41

不确定我完全理解你的意思,听起来你只是想捕获执行的输出,但无法判断你是否真的意味着你想完全避免 SQL*Plus。从我第一次阅读来看,这很简单:

sqlplus -s user/password @filename > outputfile

……但这让我觉得我错过了一些重要的事情。

Not sure I quite understand what you mean, it sounds like you just want to capture the output of the execution, but can't tell if you actually mean that you want to avoid SQL*Plus completely. From my first reading this is as simple as:

sqlplus -s user/password @filename > outputfile

... but that makes me think I've missed something important.

感悟人生的甜 2024-09-20 19:56:41

不这么认为,请参阅此演示文稿 由 Pete Finnigan 撰写,了解一些编译器内部结构。
它列出了 ANTLR 语法 文件

我还看到过有关 Scala PL/SQL 的组合器 解析器实现。

Dont think so, see this presentation by Pete Finnigan for some compiler internals.
It lists an ANTLR grammar file that you could use.

I have also seen mentions about Scala combinator parser implementations for PL/SQL.

抱着落日 2024-09-20 19:56:41

如果您只需要输出源 - USER_SOURCE。

我做了很多动态生成包的工作,并且编写了提取、添加附加代码和重新编译包的代码。

最简单的是,您只需将 CREATE PACKAGE 命令包装为动态 SQL。

EXECUTE IMMEDIATE 
    'CREATE OR REPLACE PACKAGE myPackageName AS '||pPackageSource;

然而,这意味着您的源只是一个字符串。我使用旧的 DBMS_SQL.PARSE 方法,它可以接受 VARCHAR2 行数组 (dbms_sql.varchar2s)。

示例 - 将源代码从 user_source 拉入 varchar 2s,然后通过 dbms_sql 重新编译相同的包。

DECLARE
    lCid INTEGER;
    lError INTEGER;
    lSource dbms_sql.varchar2s;

    FUNCTION fSource(
        pName IN VARCHAR2,
        pType IN VARCHAR2)
    RETURN dbms_sql.varchar2s
    IS
        CURSOR cSource IS
        SELECT  RTRIM(text,CHR(10))
        FROM    user_source
        WHERE   name = pName
        AND     type = pType
        ORDER BY line;
        lSource pp_type.gtyp_ArrayOfSource;
    BEGIN
       OPEN cSource;
       FETCH cSourcee BULK COLLECT INTO lSource;
       CLOSE cSource;
       RETURN lSource;
     END fSource;
BEGIN
    lSource := fSource(pName => 'myPackageName',pType => 'PACKAGE');
    /* Add CREATE or REPLACE to the start of the source */
    lSource(1) := 'CREATE OR REPLACE '||lSource(1);
-- Cannot use EXECUTE IMMEDIATE as this is an ARRAY
    lCid := dbms_sql.OPEN_CURSOR;
    --
    dbms_sql.parse(
       c    => lCid ,
       statement => lSource,
       lb   => 1,
       ub   => p_source.count,
       lfflg    => true,
       language_flag => dbms_sql.v7
   );
   dbms_sql.close_cursor (lCid);
END;

这可以很容易地更改为从文件、HTTP 服务等中提取源代码 - pl/sql 代码/数据库可以访问的任何内容。

实际代码包括验证、检查结果是否有效、通过电子邮件发送与 user_source 中的行匹配的任何错误(来自 user_errors)等。

安全性

代码需要以安装包的权限运行 - 这可能意味着针对比执行用户具有更高权限的用户安装软件包。

如果您这样做,您需要非常小心哪些接口暴露给“普通”数据库用户 - 即您不想创建任何让普通用户提取或修改包源或权限的东西。

我的方法是为所有服务功能(获取源、安装、动态执行等)创建一个低级包(对普通用户隐藏),然后创建一个更高级别的包,向普通用户公开一组有限的特定操作 - 在对于您的情况,这类似于公开“reviewCode”过程。

If you just need to output the source - USER_SOURCE.

I do a lot of dynamic generation of packages, and I've written code that extracts, adds additional code, and recompiles the package.

At it's simplest you just need to wrap up your CREATE PACKAGE command as dynamic SQL.

EXECUTE IMMEDIATE 
    'CREATE OR REPLACE PACKAGE myPackageName AS '||pPackageSource;

However, that means your source is just one string. I use the older DBMS_SQL.PARSE method that can accept an array of VARCHAR2 lines (dbms_sql.varchar2s).

Example - code to pull the source from user_source into a varchar 2s, then recompile the same package via dbms_sql.

DECLARE
    lCid INTEGER;
    lError INTEGER;
    lSource dbms_sql.varchar2s;

    FUNCTION fSource(
        pName IN VARCHAR2,
        pType IN VARCHAR2)
    RETURN dbms_sql.varchar2s
    IS
        CURSOR cSource IS
        SELECT  RTRIM(text,CHR(10))
        FROM    user_source
        WHERE   name = pName
        AND     type = pType
        ORDER BY line;
        lSource pp_type.gtyp_ArrayOfSource;
    BEGIN
       OPEN cSource;
       FETCH cSourcee BULK COLLECT INTO lSource;
       CLOSE cSource;
       RETURN lSource;
     END fSource;
BEGIN
    lSource := fSource(pName => 'myPackageName',pType => 'PACKAGE');
    /* Add CREATE or REPLACE to the start of the source */
    lSource(1) := 'CREATE OR REPLACE '||lSource(1);
-- Cannot use EXECUTE IMMEDIATE as this is an ARRAY
    lCid := dbms_sql.OPEN_CURSOR;
    --
    dbms_sql.parse(
       c    => lCid ,
       statement => lSource,
       lb   => 1,
       ub   => p_source.count,
       lfflg    => true,
       language_flag => dbms_sql.v7
   );
   dbms_sql.close_cursor (lCid);
END;

This could easily be changed to extract the source from a file, HTTP service, etc - anything that the pl/sql code / database can reach.

The actual code includes validation, checks the result is valid, emails any errors (from user_errors) matched against the lines in user_source, etc.

Security

The code needs to be running with privileges to install a package - this may mean installing the package against a user with higher privileges than the executing user.

If you are doing this, you need to be very careful about what interfaces are exposed to 'normal' DB users - i.e. you do not want to create anything that lets a normal user extract or modify the package source or privileges.

My approach was creating a low-level package (hidden from normal users) for all the service functions (get source, install, dynamic execute, etc) and then a higher level package that exposed a limited set of specific actions to regular users - in your case this would be something like exposing a 'reviewCode' procedure.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文