>

SQL Server 2008에서 테이블을 유형으로 만들었습니다.

SQL Server 2008은 테이블 값 매개 변수를 IN 매개 변수로 저장 프로 시저에 전달할 수 있도록 지원합니다. 잘 작동하고 있습니다.

이제 Oracle에서 동일한 접근 방식을 수행해야합니다.

나는 PLSQLAssociativeArray 를 통해 그것을했다  그러나 연관 배열의 한계는 동 질적입니다 (모든 요소는 동일한 유형이어야합니다).

SQL Server 2008의 테이블 반환 매개 변수의 경우 가능합니다.

Oracle에서 동일하게 달성하는 방법?

다음은 SQL Server 2008의 유형 및 저장 프로 시저입니다.

CREATE TYPE [dbo].[EmployeeType] AS TABLE(  
    [EmployeeID] [int] NULL,  
    [EmployeeName] [nvarchar](50) NULL  
)  
GO

CREATE PROCEDURE [dbo].[TestCustom] @location EmployeeType READONLY  
AS  
insert into Employee (EMP_ID,EMP_NAME)   
SELECT EmployeeID,EmployeeName  
FROM @location;
GO

NHibernate에서 전화

  var dt = new DataTable();  
   dt.Columns.Add("EmployeeID", typeof(int));  
   dt.Columns.Add("EmployeeName", typeof(string));  
   dt.Rows.Add(new object[] { 255066, "Nachi11" });  
   dt.Rows.Add(new object[] { 255067, "Nachi12" });                 
   ISQLQuery final = eventhistorysession.CreateSQLQuery("Call TestCustom @pLocation = :id");  
   IQuery result = final.SetStructured("id", dt);  
   IList finalResult = result.List();


  • 답변 # 1

    CREATE OR REPLACE TYPE employeeType AS OBJECT (employeeId INT, employeeName VARCHAR2(50));
    CREATE TYPE ttEmployeeType AS TABLE OF employeeType;
    CREATE PROCEDURE testCustom (pLocation ttEmployeeType)
    AS
    BEGIN
            INSERT
            INTO    employee (emp_id, emp_name)
            SELECT  *
            FROM    TABLE(pLocation);
    END;
    
    

  • 답변 # 2

    nHibernate 또는 ODP.NET을 사용하여 Oracle 객체 테이블 매개 변수 (예 : @Quassnoi의 답변 참조)를 사용할 수 없음을 이해합니다. ODP.NET에서 지원하는 유일한 컬렉션 유형은 PLSQLAssociativeArray 입니다. .

    그러나 연관 배열을 사용하는 SQL Server TVP와 동일한 결과를 쉽게 얻을 수 있습니다. 비결은 전체 테이블에 단일 매개 변수 대신 각 매개 변수에 대한 배열을 정의하는 것입니다.

    찾을 수 없었던 완벽한 개념 증명 솔루션을 게시하고 있습니다.

    오라클 스키마

    스키마에는 테이블 및 패키지 삽입 절차가 포함됩니다. 각 매개 변수를 열로 취급하고 각 배열이 최소한 첫 번째 배열만큼 길다고 가정합니다.

    create table test_table
    (
        foo number(9),
        bar nvarchar2(64)
    );
    /
    create or replace package test_package as
        type number_array is table of number(9) index by pls_integer;
        type nvarchar2_array is table of nvarchar2(64) index by pls_integer;
        procedure test_proc(p_foo number_array, p_bar nvarchar2_array);
    end test_package;
    / 
    create or replace package body test_package as
        procedure test_proc(p_foo number_array, p_bar nvarchar2_array) as
        begin
            forall i in p_foo.first .. p_foo.last
                insert into test_table values (p_foo(i), p_bar(i));
        end;
    end test_package; 
    /
    
    
    n 최대 절전 모드 매핑
    <sql-query name="test_proc">
      begin test_package.test_proc(:foo, :bar); end;
    </sql-query>
    
    
    n 최대 절전 모드 사용자 정의 IType

    저는 훌륭한 SQL Server 관련 답변에서 개념을 빌려 ODP.NET에서 작동하도록 클래스를 약간 수정했습니다. IType 로  엄청 나서 구현 된 메소드 만 보여줍니다. 나머지는 NotImplementedException 를 던졌습니다. .

    이 코드를 프로덕션 코드에서 사용하려면 즉시 필요한 작업을 수행하더라도이 클래스를 광범위하게 테스트하지 않았다는 점에 유의하십시오.

    public class OracleArrayType<T> : IType
    {
        private readonly OracleDbType _dbType;
        public OracleArrayType(OracleDbType dbType)
        {
            _dbType = dbType;
        }
        public SqlType[] SqlTypes(IMapping mapping)
        {
            return new []{ new SqlType(DbType.Object) };
        }
        public bool IsCollectionType
        {
            get { return true; }
        }
        public int GetColumnSpan(IMapping mapping)
        {
            return 1;
        }
        public void NullSafeSet(IDbCommand st, object value, int index, ISessionImplementor session)
        {
            var s = st as OracleCommand;
            var v = value as T[];
            if (s != null && v != null)
            {
                s.Parameters[index].CollectionType = OracleCollectionType.PLSQLAssociativeArray;
                s.Parameters[index].OracleDbType = _dbType;
                s.Parameters[index].Value = value;
                s.Parameters[index].Size = v.Length;
            }
            else
            {
                throw new NotImplementedException();
            }
        }
        // IType boiler-plate implementation follows.
    
    
    생성자 매개 변수는 기본 배열 유형의 유형을 지정합니다 (즉, 문자열 배열을 전달하는 경우 OracleDbType.NVarchar2 를 전달하십시오) . 값 유형에서 DB 유형을 추론하는 방법이있을 수 있지만 아직 방법을 잘 모르겠습니다.

    IQuery 확장 방법

    이것은 타입 생성을 마무리합니다 :

    public static class OracleExtensions
    {
        public static IQuery SetArray<T>(this IQuery query, string name, OracleDbType dbType, T[] value)
        {
            return query.SetParameter(name, value, new OracleArrayType<T>(dbType));
        }
    }
    
    
    사용법

    이 모든 것을 하나로 묶기 위해 다음과 같이 수업이 사용됩니다 :

    using (var sessionFactory = new Configuration().Configure().BuildSessionFactory())
    using (var session = sessionFactory.OpenSession())
    {
        session
            .GetNamedQuery("test_proc")
            .SetArray("foo", OracleDbType.Int32, new[] { 11, 21 })
            .SetArray("bar", OracleDbType.NVarchar2, new [] { "bar0", "bar1" })
            .ExecuteUpdate();
    }
    
    
    select * from test_table 의 결과  코드를 실행 한 후 :

    FOO   BAR
    ----------------
    11    bar0
    21    bar1
    
    

관련 자료

  • 이전 cpickle을 사용하여 큰 어레이를 네트워크 드라이브에 쓰는 경우 python "ioerror - [errno 22] invalid argument"
  • 다음 javascript - 브라우저/뷰포트 대신 컨테이너 요소 내에서 고정 된 위치