Oracle과 SQL Server의 빈 처리 차이점(서로 다른 데이터베이스를 연결하는 경우)

저번의 계속.
이번에는 SQL Server, Oracle 간 데이터베이스 링크 동작을 조사했습니다.

확인


테이블


직접저번로 제작되었습니다.
DBMS도 지난번과 마찬가지로 Oracle 19c와 SQLServer 2019를 통해 진행됐다.
CreateTable(Oracle).sql
CREATE TABLE CompareTestTable
(
     Seq         NUMBER
    ,ColCHAR     CHAR(10)
    ,ColVARCHAR  VARCHAR2(10)
);

INSERT INTO CompareTestTable VALUES( 1, 'aaa',  'bbb'  );       -- スペースなし
INSERT INTO CompareTestTable VALUES( 2, 'aaa ', 'bbb ' );       -- 文字列の後にスペース
INSERT INTO CompareTestTable VALUES( 3, ' aaa', ' bbb' );       -- 文字列の前にスペース
INSERT INTO CompareTestTable VALUES( 4, ' aaa ', ' bbb ' );     -- 文字列の前後にスペース
CreateTable(SqlServer).sql
CREATE TABLE CompareTestTable
(
	 Seq	     INT
	,ColCHAR     CHAR(10)
	,ColVARCHAR  VARCHAR(10)
)
INSERT INTO CompareTestTable VALUES( 1, 'aaa',  'bbb'  );       -- スペースなし
INSERT INTO CompareTestTable VALUES( 2, 'aaa ', 'bbb ' );       -- 文字列の後にスペース
INSERT INTO CompareTestTable VALUES( 3, ' aaa', ' bbb' );       -- 文字列の前にスペース
INSERT INTO CompareTestTable VALUES( 4, ' aaa ', ' bbb ' );     -- 文字列の前後にスペース

SQL Server→Oracle(SQL Server를 사용한 링크 서버, Oracle 테이블 참조)


※ 링크 서버는 "ORIACLE"이라는 이름으로 작성됩니다.테이블은 Oracle 데이터베이스의 TEST USER 모드에 있습니다.
select * from [ORACLE]..[TEST_USER].[COMPARETESTTABLE] where ColCHAR = 'aaa';       -- SEQ=1,2のデータがヒット
select * from [ORACLE]..[TEST_USER].[COMPARETESTTABLE] where ColCHAR = 'aaa ';      -- SEQ=1,2のデータがヒット
select * from [ORACLE]..[TEST_USER].[COMPARETESTTABLE] where ColCHAR = ' aaa';      -- SEQ=3,4のデータがヒット
select * from [ORACLE]..[TEST_USER].[COMPARETESTTABLE] where ColCHAR = ' aaa ';     -- SEQ=3,4のデータがヒット

select * from [ORACLE]..[TEST_USER].[COMPARETESTTABLE] where ColVARCHAR = 'bbb';    -- SEQ=1,2のデータがヒット
select * from [ORACLE]..[TEST_USER].[COMPARETESTTABLE] where ColVARCHAR = 'bbb ';   -- SEQ=1,2のデータがヒット
select * from [ORACLE]..[TEST_USER].[COMPARETESTTABLE] where ColVARCHAR = ' bbb';   -- SEQ=3,4のデータがヒット
select * from [ORACLE]..[TEST_USER].[COMPARETESTTABLE] where ColVARCHAR = ' bbb ';  -- SEQ=3,4のデータがヒット
마지막 SQL Server 검증 결과와 같다.
현상으로 추정하면 Oracle의 데이터를 SQL Server 측에 가져간 다음에 SQL Server로 검색 조건을 재평가합니까?
참고로 OPEN QUERY를 사용하면 Oracle 측에서 조회를 실행할 때지난번 갑골문 검증 결과와 같습니다.그럼요.
https://docs.microsoft.com/ja-jp/sql/t-sql/functions/openquery-transact-sql?view=sql-server-ver15
select * from openquery(ORACLE,'select * from CompareTestTable where ColCHAR = ''aaa''')       -- SEQ=1,2のデータがヒット
select * from openquery(ORACLE,'select * from CompareTestTable where ColCHAR = ''aaa ''')      -- SEQ=1,2のデータがヒット
select * from openquery(ORACLE,'select * from CompareTestTable where ColCHAR = '' aaa''')      -- SEQ=3,4のデータがヒット
select * from openquery(ORACLE,'select * from CompareTestTable where ColCHAR = '' aaa ''')     -- SEQ=3,4のデータがヒット
  
select * from openquery(ORACLE,'select * from CompareTestTable where ColVARCHAR = ''bbb''')    -- SEQ=1のデータがヒット
select * from openquery(ORACLE,'select * from CompareTestTable where ColVARCHAR = ''bbb ''')   -- SEQ=2のデータがヒット
select * from openquery(ORACLE,'select * from CompareTestTable where ColVARCHAR = '' bbb''')   -- SEQ=3のデータがヒット
select * from openquery(ORACLE,'select * from CompareTestTable where ColVARCHAR = '' bbb ''')  -- SEQ=4のデータがヒット

Oracle → SQL Server(Oracle Database Link 사용, SQL Server 테이블 참조)


※ Database Link는'SQL SERVER'라는 이름으로 제작되었습니다.
select * from COMPARETESTTABLE@SQL_SERVER where "ColCHAR" = 'aaa';       -- SEQ=1,2のデータがヒット
select * from COMPARETESTTABLE@SQL_SERVER where "ColCHAR" = 'aaa ';      -- SEQ=1,2のデータがヒット
select * from COMPARETESTTABLE@SQL_SERVER where "ColCHAR" = ' aaa';      -- SEQ=3,4のデータがヒット
select * from COMPARETESTTABLE@SQL_SERVER where "ColCHAR" = ' aaa ';     -- SEQ=3,4のデータがヒット

select * from COMPARETESTTABLE@SQL_SERVER where "ColVARCHAR" = 'bbb';    -- SEQ=1,2のデータがヒット
select * from COMPARETESTTABLE@SQL_SERVER where "ColVARCHAR" = 'bbb ';   -- SEQ=1,2のデータがヒット
select * from COMPARETESTTABLE@SQL_SERVER where "ColVARCHAR" = ' bbb';   -- SEQ=3,4のデータがヒット
select * from COMPARETESTTABLE@SQL_SERVER where "ColVARCHAR" = ' bbb ';  -- SEQ=3,4のデータがヒット
이것은 의외의 결과다.
결과가 지난번 갑골문 검증 결과와 같을 것으로 생각했는데 결과는 SQL Server와 같습니다.
SQL Server 측에서 질의를 수행했는지 여부는 현상으로 추정됩니다.
신경 쓰이기 때문에 아래 글을 참고하여 SQL Server 측의 조회 기록을 조사했습니다.
http://www.it-view.net/sql-server-실행된 ql 역사 확인 - 338.html
SELECT TOP 1000
--作成時間
QS.creation_time,
--SQL文
SUBSTRING(ST.text,(QS.statement_start_offset/2)+1,
((CASE QS.statement_end_offset WHEN -1 THEN DATALENGTH(st.text)
ELSE QS.statement_end_offset END - QS.statement_start_offset)/2) + 1
) AS statement_text,
--実行SQL文
ST.text,
--実行計画
QS.total_worker_time,
QS.last_worker_time,
QS.max_worker_time,
QS.min_worker_time
FROM
sys.dm_exec_query_stats QS
--キーワード
CROSS APPLY
sys.dm_exec_sql_text(QS.sql_handle) ST
ORDER BY
QS.creation_time DESC
결과 질의가 SQL Server 측에서 여전히 수행되고 있음을 알 수 있습니다.

총결산


지난번 검증을 포함해 알고 있는 것은 다음과 같다.
문자열의 앞뒤에 공백이 있는 데이터를 처리할 때
  • ORACLE과 SQL Server가 모두 CHAR의 열이면 같은 검색 결과를 얻지만 VARCHAR 열은 다른 검색 결과를 얻는다.
  • SQL Server→Oracle(SQL Server의 링크 서버 사용, Oracle의 표 참조) 시 SQL Server 측의 검색 규격으로 문의합니다.
  • Oracle → SQL Server(Oracle의 Database Link를 사용하여 SQL Server의 표를 참조)할 때도 SQL Server 측의 검색 규격으로 문의합니다.
  • 상술한성능 개선 등을 통해 수정할 때 Oracle Database Link를 사용하는 액세스에서 소재 보기로 변경되는 경우도 실제 업무입니다.
    그러나 소재시도의 실체는 갑골문의 표일 뿐이기 때문에 소재시도의 검색은지난번 갑골문 검증 결과과 같다.
    따라서 쉽게 변경할 경우 변경 전후로 동일한 결과를 얻지 못할 수도 있다.
    (또는 Database Link 액세스를 소재 뷰로 변경했을 때 실제로 경험했습니다. 이 기사를 쓰고 싶었던 경위이기도 합니다.)

    좋은 웹페이지 즐겨찾기