ODP.NET,托管读取 LONG 列结果为 ORA-01009

问题描述

我正在尝试在我的 .net 应用程序中获取视图的来源。 为此,我查询 $array = Search-ADAccount -LockedOut | ForEach-Object { "$($_.SamAccountName)" } Get-Content -Path "path-to-txt-file" | ForEach-Object { if ($array.Contains($_.Split(" ")[0].Trim())) { Write-Host "Locked ID: $($_.Split(" ")[-1].Trim())" } } :它有一列 DBA_VIEWS 正是我需要的。类型为 TEXT

如果我使用非托管驱动程序执行此操作,则一切正常。 与托管驱动程序相同的代码导致 LONG。 使用断点围绕命令添加一个事务“慢”步骤有时会导致相同的代码工作。

ODP.NET 版本是 19,Oracle DB 是 18c 快捷版。奇怪的是,无论驱动程序类型如何,相同的代码在 Oracle Database 12c 上都能正常工作。

我是否需要更改数据库代码中的某些设置?我完全迷失在这里

我用于测试的代码

ORA-01009: missing mandatory parameter

解决方法

遗憾的是,Oracle 已弃用 LONG 数据类型多年,但内部数据仍多次使用 LONG 数据。

您可以编写一个函数,然后通过调用该函数来获取数据:

create or replace function GetViewText(v in varchar2) return clob is     
 ret CLOB;      
BEGIN

    FOR aRow IN (SELECT TEXT FROM DBA_VIEWS WHERE VIEW_NAME = v) LOOP
        ret := aRow.TEXT;
        -- or ret := TO_CLOB(aRow.TEXT);
    END LOOP;  
    RETURN ret;    
END;
,

您可以使用带有输出参数和调用 ExecuteNonQuery 的匿名块。您的命令文本将是

"begin select TEXT into :0 from DBA_VIEWS where VIEW_NAME = :1; end;"

添加2个参数。确保

' Parameter #1 has
p.Direction = ParameterDirection.Output
p.OracleDbType = OracleDbType.Long
p.Size = 1000000

并使用命令 cmd.ExecuteNonQuery()。然后,当检索到参数时,只需使用其值

Dim txt As String = cmd.Parametersp[0].Value.ToString()
,

this 答案的另一种方式是(ab)使用 dbms_xmlgen.getxml。 我们可以使用它来查询单个视图的代码(如我原来的问题)

with input as (
 select
 :0 as VIEW_NAME
 from dual
)
SELECT
substr(
    text_xml,instr(text_xml,'<LONGCOL>') + length('<LONGCOL>'),'</LONGCOL>',-1) - (instr(text_xml,'<LONGCOL>') + length('<LONGCOL>'))
) as TEXT
from
(
    -- getxml can return malformed xml (which is good in this case)
    -- while getxmltype can not.
    select dbms_xmlgen.getxml(q'{
    SELECT TEXT as LONGCOL
    FROM SYS.DBA_VIEWS
    WHERE VIEW_NAME = '}' || input.VIEW_NAME || q'{'
}') as text_xml
from input
)

或创建我们自己的 DBA_VIEWS 版本。

create or replace view APP_SCHEMA.DBA_VIEWS
as
select
    OWNER,VIEW_NAME,TEXT_LENGTH,case
        when (TEXT_VC is not null and TEXT_LENGTH <= 4000)
            then to_clob(TEXT_VC)
        when TEXT is NULL
            then NULL
        else (
             SELECT
               substr(
                    text_xml,--instr(text_xml,'<LONGCOL>') + length('<LONGCOL>'))
                    TEXT_LENGTH
               ) as TEXT
              from
               (
                -- getxml can return malformed xml (which is good in this case)
                -- while getxmltype can not.
                select dbms_xmlgen.getxml(q'{
                SELECT TEXT as LONGCOL
                FROM SYS.DBA_VIEWS
                WHERE OWNER = '}' || OWNER || q'{'
                and VIEW_NAME = '}' || VIEW_NAME || q'{'
                }') as text_xml
                from dual
               )
        )
    end as TEXT,TEXT_VC,TYPE_TEXT_LENGTH,TYPE_TEXT,OID_TEXT_LENGTH,OID_TEXT,VIEW_TYPE_OWNER,VIEW_TYPE,SUPERVIEW_NAME,EDITIONING_VIEW,READ_ONLY,CONTAINER_DATA,BEQUEATH,ORIGIN_CON_ID,DEFAULT_COLLATION,CONTAINERS_DEFAULT,CONTAINER_MAP,EXTENDED_DATA_LINK,EXTENDED_DATA_LINK_MAP,HAS_SENSITIVE_COLUMN
from sys.dba_views
;