DBMS_OUTPUT에서 출력 버퍼를 가져오는 중입니다.C#의 GET_LINES
저는 그 결과물을 얻으려고 노력하고 있습니다.DBMS_OUTPUT.PUT_LINE()
C#을 통한 익명 PL/SQL 블록의 메서드입니다.여기서 다른 관련 질문 몇 가지를 살펴보았지만 여전히 문제가 있습니다.익명 블록 실행의 반환 코드가 반환됩니다.-1
서류에 근거하여 정확해야 합니다.
내가 설정하는 중입니다.DBMS_OUTPUT.ENABLE()
로.NULL
특정 버퍼 크기를 설정하지 않으려면 다음을 사용합니다.DBMS_OUTPUT.GET_LINES()
버퍼에서 줄을 가져오는 방법입니다.
버퍼에서 아무것도 반환하지 않습니다(공백).OracleString[]
) 및 반환0
lines. 제 익명 PL/SQL 블록은 이렇게 간단하지만, 어떤 경우에도 작동합니다.
DECLARE
lvsName VARCHAR2(6) := 'Oracle';
BEGIN
DBMS_OUTPUT.PUT_LINE('Do you see me?');
DBMS_OUTPUT.PUT_LINE('My name is: ' || lvsName);
END;
제가 무엇을 빠뜨리고 있나요?
using (OracleDataAdapter oda = new OracleDataAdapter())
using (OracleCommand cmd = new OracleCommand(sql, _connection))
{
// Execute anonymous PL/SQL block
cmd.CommandType = CommandType.Text;
var res = cmd.ExecuteNonQuery();
// Set output Buffer
cmd.CommandText = "BEGIN DBMS_OUTPUT.ENABLE(NULL); END;";
cmd.CommandType = CommandType.Text;
cmd.ExecuteNonQuery();
// Get output
cmd.CommandText = "BEGIN DBMS_OUTPUT.GET_LINES(:outString, :numLines); END;";
cmd.CommandType = CommandType.Text;
cmd.Parameters.Clear();
cmd.Parameters.Add(new OracleParameter("outString", OracleDbType.Varchar2, int.MaxValue, ParameterDirection.Output));
cmd.Parameters["outString"].CollectionType = OracleCollectionType.PLSQLAssociativeArray;
cmd.Parameters["outString"].Size = sql.Length;
cmd.Parameters["outString"].ArrayBindSize = new int[sql.Length];
cmd.Parameters.Add(new OracleParameter("numLines", OracleDbType.Int32, ParameterDirection.InputOutput));
cmd.Parameters["numLines"].Value = 10; // Get 10 lines
cmd.ExecuteNonQuery();
int numLines = Convert.ToInt32(cmd.Parameters["numLines"].Value.ToString());
string outString = string.Empty;
// Try to get more lines until there are zero left
while (numLines > 0)
{
for (int i = 0; i < numLines; i++)
{
OracleString s = (OracleString)cmd.Parameters["outString"].Value;
outString += s.ToString();
}
cmd.ExecuteNonQuery();
numLines = Convert.ToInt32(cmd.Parameters["numLines"].Value.ToString());
}
return outString;
}
코드의 주요 문제는 출력 버퍼의 각 요소에 대한 바인딩 크기를 설정하지 않았다는 것입니다.또한 결과를 검색할 때 출력 버퍼를 제대로 인덱싱하지 않았습니다.마지막으로, 실행 순서도 역할을 합니다. 익명 코드 블록을 실행하기 전에 먼저 출력을 활성화해야 합니다.모든 변경 사항은 다음 MCVE에 설명되어 있습니다.작동하기 위해 필요한 변경 사항만 수행되었습니다.
static void Main(string[] args)
{
string str = "User Id=xxx; password=xxx; Data Source=localhost:1521/xxx;";
string sql = @"DECLARE lvsName VARCHAR2(6) := 'Oracle'; BEGIN DBMS_OUTPUT.PUT_LINE('Do you see me?'); DBMS_OUTPUT.PUT_LINE('My name is: ' || lvsName); END;";
OracleConnection _connection = new OracleConnection(str);
try
{
_connection.Open();
//adapter not being used
//using (OracleDataAdapter oda = new OracleDataAdapter())
using (OracleCommand cmd = new OracleCommand(sql, _connection))
{
// First enable buffer output
// Set output Buffer
cmd.CommandText = "BEGIN DBMS_OUTPUT.ENABLE(NULL); END;";
cmd.CommandType = CommandType.Text;
cmd.ExecuteNonQuery();
// Then execute anonymous block
// Execute anonymous PL/SQL block
cmd.CommandText = sql;
cmd.CommandType = CommandType.Text;
var res = cmd.ExecuteNonQuery();
// Get output
cmd.CommandText = "BEGIN DBMS_OUTPUT.GET_LINES(:outString, :numLines); END;";
cmd.CommandType = CommandType.Text;
cmd.Parameters.Clear();
cmd.Parameters.Add(new OracleParameter("outString", OracleDbType.Varchar2, int.MaxValue, ParameterDirection.Output));
cmd.Parameters["outString"].CollectionType = OracleCollectionType.PLSQLAssociativeArray;
cmd.Parameters["outString"].Size = sql.Length;
cmd.Parameters["outString"].ArrayBindSize = new int[sql.Length];
// set bind size for each array element
for (int i = 0; i < sql.Length; i++)
{
cmd.Parameters["outString"].ArrayBindSize[i] = 32000;
}
cmd.Parameters.Add(new OracleParameter("numLines", OracleDbType.Int32, ParameterDirection.InputOutput));
cmd.Parameters["numLines"].Value = 10; // Get 10 lines
cmd.ExecuteNonQuery();
int numLines = Convert.ToInt32(cmd.Parameters["numLines"].Value.ToString());
string outString = string.Empty;
// Try to get more lines until there are zero left
while (numLines > 0)
{
for (int i = 0; i < numLines; i++)
{
// use proper indexing here
//OracleString s = (OracleString)cmd.Parameters["outString"].Value;
OracleString s = ((OracleString[])cmd.Parameters["outString"].Value)[i];
outString += s.ToString();
// add new line just for formatting
outString += "\r\n";
}
cmd.ExecuteNonQuery();
numLines = Convert.ToInt32(cmd.Parameters["numLines"].Value.ToString());
}
Console.WriteLine(outString);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
_connection.Close();
_connection.Dispose();
Console.WriteLine("Press RETURN to exit.");
Console.ReadLine();
}
출력 결과는 다음과 같습니다.
Do you see me?
My name is: Oracle
Press RETURN to exit.
솔루션에 대한 좋은 근거를 제공한 jsanalytics의 위 답변에 감사드립니다.하지만 위 솔루션에는 몇 가지 문제가 있는데, 대부분은 sql 사용과 관련이 있습니다.길이는 말이 안 되는 곳이 많습니다.다음은 몇 가지 문제를 해결하는 재사용 가능한 솔루션입니다.
using Oracle.DataAccess.Client;
using Oracle.DataAccess.Types;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
namespace MyNamespace
{
public static class DbmsOutputHelper
{
public const int DefaultReadBatchSize = 10;
public static void EnableDbmsOutput(this OracleConnection conn)
{
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = "DBMS_OUTPUT.ENABLE";
cmd.CommandType = CommandType.StoredProcedure;
cmd.ExecuteNonQuery();
}
}
public static void DisableDbmsOutput(this OracleConnection conn)
{
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = "DBMS_OUTPUT.DISABLE";
cmd.CommandType = CommandType.StoredProcedure;
cmd.ExecuteNonQuery();
}
}
public static List<string> ReadDbmsOutput(this OracleConnection conn, int readBatchSize = DefaultReadBatchSize)
{
if (readBatchSize <= 0)
{
throw new ArgumentOutOfRangeException(nameof(readBatchSize), "must be greater than zero");
}
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = "DBMS_OUTPUT.GET_LINES";
cmd.CommandType = CommandType.StoredProcedure;
var linesParam = cmd.Parameters.Add(new OracleParameter("lines", OracleDbType.Varchar2, int.MaxValue, ParameterDirection.Output));
linesParam.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
linesParam.Size = readBatchSize;
linesParam.ArrayBindSize = Enumerable.Repeat(32767, readBatchSize).ToArray(); // set bind size for each array element
var numLinesParam = cmd.Parameters.Add(new OracleParameter("numlines", OracleDbType.Int32, ParameterDirection.InputOutput));
var result = new List<string>();
int numLinesRead;
do
{
numLinesParam.Value = readBatchSize;
cmd.ExecuteNonQuery();
numLinesRead = ((OracleDecimal)numLinesParam.Value).ToInt32();
var values = (OracleString[])linesParam.Value;
for (int i = 0; i < numLinesRead; i++)
{
result.Add(values[i].ToString());
}
} while (numLinesRead == readBatchSize);
return result;
}
}
}
}
제가 보기엔 당신이 순서를 잘못 알고 있는 것 같은데요...
// Execute anonymous PL/SQL block
cmd.CommandType = CommandType.Text;
var res = cmd.ExecuteNonQuery();
// Set output Buffer
cmd.CommandText = "BEGIN DBMS_OUTPUT.ENABLE(NULL); END;";
cmd.CommandType = CommandType.Text;
cmd.ExecuteNonQuery();
// Get output
cmd.CommandText = "BEGIN DBMS_OUTPUT.GET_LINES(:outString, :numLines); END;";
설정(활성화) 사이에DBMS_OUTPUT
다음을 사용하여 출력을 얻습니다.GET_LINES
쓰기 명령어가 되어야 하지만, 대신에 가장 먼저 실행하는 명령어입니다.
순서를 바꿔보세요.제가 안 해봐서 잘 되는지 알려주세요 (C#에 익숙하지 않아서요...자바로 가지고 있습니다.).
저는 C#을 말할 수 없지만 numLines 변수에 값을 할당하는 코드를 볼 수 없습니다.
DBMS_OUTPUT.GET_LINES (
lines OUT CHARARR,
numlines IN OUT INTEGER);
plsql의 예:
DECLARE
v_array DBMS_OUTPUT.CHARARR;
v_lines NUMBER;
BEGIN
DBMS_OUTPUT.PUT_LINE ('aaaaa');
DBMS_OUTPUT.put_line ('bbbb');
DBMS_OUTPUT.put_line ('ccccc');
v_lines := 1000; -- Number of lines you want to retrieve from the buffer.
DBMS_OUTPUT.GET_LINES (v_array, v_lines);
DBMS_OUTPUT.put_line(v_lines); -- Lines retrieved from buffer.
FOR idx IN nvl(v_array.FIRST,1) .. nvl(v_array.LAST,-1)
LOOP
DBMS_OUTPUT.put_line (v_array (idx));
END LOOP;
END;
언급URL : https://stackoverflow.com/questions/53402356/getting-output-buffer-from-dbms-output-get-lines-in-c-sharp
'programing' 카테고리의 다른 글
현재 클래스의 이름을 가져오시겠습니까? (0) | 2023.09.04 |
---|---|
Swift용 Xcode에서 코드 포맷터를 사용하는 방법은 무엇입니까? (0) | 2023.09.04 |
mysql / Maria DB 대소문자 구분 검색 (0) | 2023.09.04 |
루프가 있는 특정 테이블에서 N명의 사용자를 한 번에 선택하려면 어떻게 해야 합니까? (0) | 2023.09.04 |
iOS Safari – 오버스크롤을 비활성화하면서 스크롤 가능한 div를 정상적으로 스크롤할 수 있도록 하는 방법은 무엇입니까? (0) | 2023.09.04 |