모든 (또는 대부분의) 데이터베이스에서 작동하는 효율적인 SQL 테스트 쿼리 또는 유효성 검사 쿼리


148

많은 데이터베이스 연결 풀링 라이브러리는 유휴 상태에 대한 SQL 연결을 테스트하는 기능을 제공합니다. 예를 들어, JDBC 풀링 라이브러리 c3p0 에는라는 속성이 있으며,이 속성 preferredTestQuery은 구성된 간격으로 연결에서 실행됩니다. 마찬가지로 Apache Commons DBCP에는 validationQuery.

내가 본 많은 예제 쿼리 는 MySQL에 SELECT 1;대한 것이며 테스트 쿼리의 값으로 사용 하는 것이 좋습니다 . 그러나,이 쿼리는 일부 데이터베이스 (있는 예를 들어, HSQLDB, 작동하지 않습니다 SELECT 1기대 FROM절).

동등하지만 효율적이지만 모든 SQL 데이터베이스에서 작동하는 데이터베이스에 구애받지 않는 쿼리가 있습니까?

편집하다:

존재하지 않는 경우 (다른 경우에 해당되는 경우) 다양한 데이터베이스 공급자에 대해 작동하는 SQL 쿼리 세트를 제안 할 수 있습니까? 데이터베이스 프로 바이더 구성을 기반으로 사용할 수있는 명령문을 프로그래밍 방식으로 결정하려고합니다.



1
참고 : 테스트 쿼리 구성은 더 이상 필요하지 않습니다. 아래 답변을 참조하십시오.
Tim Büthe

답변:


274

여기에 대한 답변 중 일부의 도움과 함께 약간의 연구를 한 후에 :

SELECT 1


SELECT 1 FROM DUAL

  • 신탁

SELECT 1 FROM any_existing_table WHERE 1=0

또는

SELECT 1 FROM INFORMATION_SCHEMA.SYSTEM_USERS

  • HSQLDB (버전 1.8.0.10으로 테스트)

    참고 : WHERE 1=0두 번째 쿼리에서 절을 사용하려고 시도했지만 validationQuery쿼리가 행을 반환하지 않기 때문에 Apache Commons DBCP의 값으로 작동 하지 않았습니다.


VALUES 1 또는 SELECT 1 FROM SYSIBM.SYSDUMMY1

  • Apache Derby (대 시크 를 통해 )

SELECT 1 FROM SYSIBM.SYSDUMMY1

  • DB2

select count(*) from systables

  • 인포믹스

"any_existing_table WHERE 1 = 0에서 SELECT 1"이어야합니다. 그렇지 않으면 호출이 매우 느려질 수 있습니다. 그건 그렇고, SELECT 1과 SELECT 1 FROM DUAL도 H2와 함께 작동합니다.
Thomas Mueller

2
나는이 오래된 몇 년 알고 있지만 모두를 추가 할 수 있습니다 VALUES 1SELECT 1 FROM SYSIBM.SYSDUMMY1아파치 더비
daiscog

OP가 Java 답변을 원한다고 가정합니다. Java 6에서는이 답변이 구식이라고 생각합니다. 이 페이지의 다른 곳에서 내 답변을 참조하십시오.
peterh

이 두 가지를 DB2에 추가 할 수 있습니다. "sysibm.sysdummy1에서 현재 날짜 선택"Informix : "systables에서 count (*) 선택"
Michael

@Michael 수정 사항을 제안하고 싶으면 승인하겠습니다. 또한 몇 가지 담당자가 있습니다.
Rob Hruska

22

드라이버가 JDBC 4 호환 인 경우 연결을 테스트하기 위해 전용 쿼리가 필요하지 않습니다. 대신 연결 을 테스트 할 Connection.isValid 가 있습니다.

JDBC 4는 2006 년부터 Java 6의 일부이며 드라이버는이를 지원해야합니다!

HikariCP와 같은 유명한 연결 풀에는 여전히 테스트 쿼리를 지정하기위한 구성 매개 변수가 있지만 사용하지 않는 것이 좋습니다.

TestconnectionTestQuery

드라이버가 JDBC4를 지원하는 경우이 속성을 설정하지 않는 것이 좋습니다. JDBC4 Connection.isValid () API를 지원하지 않는 "레거시"데이터베이스 용입니다. 데이터베이스에서 연결이 아직 활성 상태인지 확인하기 위해 풀에서 연결을 제공하기 직전에 실행되는 쿼리입니다. 이 속성없이 풀을 다시 실행하면 드라이버가 JDBC4 호환이 아닌 경우 HikariCP가 오류를 기록합니다. 기본값 : 없음


9

불행히도 데이터베이스에 관계없이 항상 작동하는 SELECT 문은 없습니다.

대부분의 데이터베이스는 다음을 지원합니다.

SELECT 1

일부 데이터베이스는이를 지원하지 않지만 테이블이 필요 없을 때 사용할 수있는 DUAL이라는 테이블이 있습니다.

SELECT 1 FROM DUAL

MySQL은 호환성을 위해이를 지원하지만 모든 데이터베이스가 지원하는 것은 아닙니다. 위의 방법 중 하나를 지원하지 않는 데이터베이스에 대한 해결 방법은 단일 행을 포함하는 DUAL이라는 테이블을 작성하는 것입니다.

HSQLDB는 위의 어느 것도 지원하지 않으므로 DUAL 테이블을 작성하거나 다음을 사용할 수 있습니다.

SELECT 1 FROM any_table_that_you_know_exists_in_your_database

답변 해주셔서 감사합니다. "항상 작동하는 SELECT 문이 없습니다"문으로 인해 내 질문을 약간 업데이트했습니다. SELECT 1 FROM DUALHSQLDB에서도 작동하지 않습니다.
Rob Hruska

1
+1, 이것은 특히 HSQLDB 사례에 대한 연구와 함께 제공된 곳입니다.
Rob Hruska

"select 1"을 지원하지 않는 것은 무엇입니까? 이중 작업에서만 선택하십시오. 오라클은 그렇지 않습니까? SQL 서버가 아니거나 mysql 이상
NimChimpsky

+1 RDBMS 독립적 인 방법을 생각하려고 포기했습니다!
Martin Smith

2

나는 이것을 사용한다 :

select max(table_catalog) as x from information_schema.tables

postgreSQL, MySQL 및 MSSQL에 대한 연결 및 쿼리 실행 결과 (1 행)


2

나는 사용한다

Select COUNT(*) As X From INFORMATION_SCHEMA.SYSTEM_USERS Where 1=0

hsqldb 1.8.0의 경우


2

사용 테스트를 위해 select count(*), 그것은 사용에보다 효율적으로해야 select count(1)하기 때문에 *모든 컬럼 데이터를 읽을을 일으킬 수 있습니다.


1

select 1 SQL 서버에서 작동하지만 다른 것에 대해서는 확실하지 않습니다.

표준 ansi sql을 사용하여 테이블을 만든 다음 해당 테이블에서 쿼리하십시오.


ANSI SQL을 다루 create table나요?
Martin Smith

그렇습니다. ANSI 데이터 형식을 사용하는 경우 그래도 "select 1"이 작동하지 않으면 놀랍습니다.
NimChimpsky

1

OP가 Java 답변을 원한다고 가정합니다.

JDBC3 / Java 6부터는 자체 메소드를 발명하는 대신 사용해야 하는 isValid () 메소드가 있습니다.

드라이버의 구현자는이 메소드 ID가 호출 될 때 데이터베이스에 대해 일종의 쿼리를 실행해야합니다. 당신은 단순한 JDBC 사용자로서이 쿼리가 무엇인지 알거나 이해할 필요가 없습니다. JDBC 드라이버 작성자가 자신의 작업을 올바르게 수행했음을 신뢰하기 만하면됩니다.


2
OP가 프로그래밍 방식이 아닌 컨테이너의 연결 풀 구성에 대한 유효성 검사 쿼리에 대해 이야기하고 있다고 생각합니다. 예를 들어 리소스를 설정하는 Tomcat의 context.xml에서 Tomcat이 연결의 유효성을 검사하는 데 사용하는 validationQuery가 필요합니다. isValid ()를 활용하려면 Tomcat 자체를 변경해야합니다. OP가 제어 할 수있는 것은 아닙니다.
Michael

또한 "JDBC 드라이버의 작성자가 자신의 작업을 올바르게 수행했다"는 보장이 실제로 유효하지 않다는 점도 주목할 가치가 있습니다. 방금 Postgres, HSQLDB 및 H2가 메소드를 구현하는 데 신경 쓰지 않아 항상 예외가 발생한다는 것을 알았습니다.
akroy 2016 년

1

어때요?

SELECT user()

나는 이것을 전에 사용합니다 .MySQL, H2는 괜찮습니다. 다른 사람들을 모릅니다.


1

그것이 어려운 방법을 발견했습니다.

SELECT 1 FROM DUAL

MaxDB도 마찬가지입니다.


이것은 질문에 대한 답변을 제공하지 않습니다. 평판 이 충분 하면 모든 게시물댓글 수 있습니다 . 대신 asker의 설명이 필요없는 답변을 제공하십시오 . - 검토에서
피터 브리튼

나는 그것을 얻지 못하고, 받아 들인 대답에 가치를 더합니다. 그래서 문제는 어디에 있습니까?
Lars Decker 8

그리고 당신이 언급했듯이 : 나는 받아 들인 대답을 언급 할 수 없으므로 여기에 답으로 넣습니다. 평판이 없어서 도움이 될 수 있지만 게시물을 작성하지 않는 것이 좋습니다.
Lars Decker 8

TBH, 그것은 오히려 대답을 복제하는 것보다,이 ... 일발의 해야 원래의 대답에 댓글왔다. 실패하면 원본을 제안 편집했을 수 있습니다.
Peter Brittain

1

Oracle의 경우 고성능 쿼리는

select 'X' from <your_small_table> where <primay_key_coulmn> = <some_value>

이것은 성능 관점에서입니다.


0

나는 파이어 버드에 이것을 사용

select 1 from RDB$RELATION_FIELDS rows 1

0

대한 MSSQL .

이를 통해 연결된 서버가 살아 있는지 확인할 수있었습니다. Open Query 연결 및 TRY CATCH를 사용하여 오류의 결과를 유용한 정보에 넣습니다.

IF OBJECT_ID('TEMPDB..#TEST_CONNECTION') IS NOT NULL DROP TABLE #TEST_CONNECTION
IF OBJECT_ID('TEMPDB..#RESULTSERROR') IS NOT NULL DROP TABLE #RESULTSERROR
IF OBJECT_ID('TEMPDB..#RESULTSGOOD') IS NOT NULL DROP TABLE #RESULTSGOOD

DECLARE @LINKEDSERVER AS VARCHAR(25)    SET @LINKEDSERVER = 'SERVER NAME GOES HERE'
DECLARE @SQL AS VARCHAR(MAX)
DECLARE @OPENQUERY AS VARCHAR(MAX)

--IF OBJECT_ID ('dbo.usp_GetErrorInfo', 'P' ) IS NOT NULL DROP PROCEDURE usp_GetErrorInfo;  
--GO  

---- Create procedure to retrieve error information.  
--CREATE PROCEDURE dbo.usp_GetErrorInfo  
--AS  
--SELECT     
--    ERROR_NUMBER() AS ErrorNumber  
--    ,ERROR_SEVERITY() AS ErrorSeverity  
--    ,ERROR_STATE() AS ErrorState  
--    ,ERROR_PROCEDURE() AS ErrorProcedure  
--    ,ERROR_LINE() AS ErrorLine  
--    ,ERROR_MESSAGE() AS Message;  
--GO  


BEGIN TRY
SET @SQL='
SELECT 1 
'''
--SELECT @SQL
SET @OPENQUERY = 'SELECT * INTO ##TEST_CONNECTION FROM OPENQUERY(['+ @LINKEDSERVER +'],''' + @SQL + ')'
--SELECT @OPENQUERY
EXEC(@OPENQUERY)
SELECT * INTO #TEST_CONNECTION FROM ##TEST_CONNECTION
DROP TABLE ##TEST_CONNECTION
--SELECT * FROM #TEST_CONNECTION
END TRY

BEGIN CATCH
-- Execute error retrieval routine.
IF OBJECT_ID('dbo.usp_GetErrorInfo') IS NOT NULL -- IT WILL ALWAYS HAVE SOMTHING... 
    BEGIN
        CREATE TABLE #RESULTSERROR (
        [ErrorNumber]       INT
        ,[ErrorSeverity]    INT
        ,[ErrorState]       INT
        ,[ErrorProcedure]   INT
        ,[ErrorLine]        INT
        ,[Message]          NVARCHAR(MAX) 
        )
        INSERT INTO #RESULTSERROR
        EXECUTE dbo.usp_GetErrorInfo
    END
END CATCH

BEGIN 
    IF (Select ERRORNUMBER FROM #RESULTSERROR WHERE ERRORNUMBER = '1038') IS NOT NULL --'1038' FOR ME SHOWED A CONNECTION ATLEAST. 
        SELECT
        '0' AS [ErrorNumber]        
        ,'0'AS [ErrorSeverity]  
        ,'0'AS [ErrorState]     
        ,'0'AS [ErrorProcedure] 
        ,'0'AS [ErrorLine]      
        , CONCAT('CONNECTION IS UP ON ', @LINKEDSERVER) AS [Message]            
    ELSE 
        SELECT * FROM #RESULTSERROR
END

docs.microsoft.com

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.