我需要一种方法来重命名大量Oracle存储过程中的变量。我看到的问题是存储过程变量名称也是表中的列名称,因此无法进行编辑,替换。
因此,例如,在以下过程中,如何将名为COMPANYID的变量替换为PARAM_COMPANYID?
这样做的全部目的是,我们在一个不提供调用存储过程的能力的地方工作。我们确实有能力运行SQL脚本。当前,当我们运行存储过程时,我们必须手动编辑将所有变量替换为实际值。
CREATE OR REPLACE PROCEDURE SP_TEST(
, COMPANYID IN integer default null
, OUTPUT OUT types.cursor_type
) AS
BEGIN
OPEN OUTPUT FOR
SELECT
COMPANYID
FIRSTNAME,
LASTNAME,
from
(
select distinct
COMPANYID
FIRSTNAME,
LASTNAME
FROM ALL_COMPANYS C
WHERE C.COMPANYID=COMPANYID
) TEMP
where TEMP.COMPANYID = DECODE(COMPANY,0,COMPANYID,NVL(COMPANY,COMPANYID))
GROUP BY
COMPANYID
FIRSTNAME,
LASTNAME;
最终结果看起来像这样
CREATE OR REPLACE PROCEDURE SP_TEST(
, PARAM_COMPANYID IN integer default null
, OUTPUT OUT types.cursor_type
) AS
BEGIN
OPEN OUTPUT FOR
SELECT
COMPANYID
FIRSTNAME,
LASTNAME,
from
(
select distinct
COMPANYID
FIRSTNAME,
LASTNAME
FROM ALL_COMPANYS C
WHERE C.COMPANYID=PARAM_COMPANYID
) TEMP
where TEMP.COMPANYID = DECODE(COMPANY,0,COMPANYID,NVL(COMPANY,PARAM_COMPANYID))
GROUP BY
COMPANYID
FIRSTNAME,
LASTNAME;
如果有一种方法可以将所有SQL参数重命名为最终结果(如上所述),那么我可以使用C#编写一个编辑/替换过程,以将这些存储过程转换为可运行的内联脚本。
答案 0 :(得分:2)
这样的代码是不好的做法:
WHERE C.COMPANYID=COMPANYID
显然,编写该文档的开发人员认为,显然COMPANYID
是没有混叠且没有前缀的,是指相同名称的参数。实际上,编译器将应用范围最接近的匹配标签,即表列名称。因此WHERE子句被解释为
WHERE C.COMPANYID=C.COMPANYID
即where 1=1
。不好。因此,将参数重命名为独特的东西至关重要。
坏消息是,没有神奇的方法可以做到这一点。您将必须手动编辑每个过程的源。不要在全局搜索和替换操作中使用正则表达式。从您在此处发布的示例中,列引用并非始终是别名,因此无法编写搜索和替换表达式,该表达式可以告诉(例如)COMPANYID
中的GROUP BY COMPANYID
是列而不是参数。
因此,不幸的是,您需要进行冗长而乏味的工作,查找每次出现的参数名称,确定它实际上是否为参数,然后在适当时对其进行修改。尽量不要花太多时间希望写原始脚本的开发人员遭受发明性的折磨。尽管可能会很有趣,但它会分散注意力,并会导致引入新的错误或丢失现有的错误。
这是一个脚本,您可以使用该脚本来确定任务的范围(假设您具有在其中编译这些过程的架构)。
select package_name
, object_name as procedure_name
, argument_name as parameter_name
, case when length(argument_name) > 28 then '!' end as uh_oh
from user_arguments
where position > 0 -- eliminate function return values
and argument_name in ( select column_name from user_tab_columns )
order by package_name
, object_name
, position
user_tab_columns
上的子查询是可选的。它仅允许您处理当前麻烦的参数。如果要处理所有参数,请忽略它。
uh_oh
属性将标识太长而无法使用简单的P_
前缀重命名的参数。您建议的代码建议使用PARAM_
作为前缀,但是它不必要地长,并且比两个字符的前缀可能会产生更多的名称更改。