高效的SQLtesting查询或validation查询,将跨越所有(或大多数)数据库

许多数据库连接池库提供了testing其闲置SQL连接的能力。 例如,JDBC池库c3p0有一个名为preferredTestQuery的属性,它以configuration的间隔在连接上执行。 同样,Apache Commons DBCP也有validationQuery

我见过的很多示例 查询都是针对MySQL的,推荐使用SELECT 1; 作为testing查询的值。 但是,这个查询不适用于某些数据库(例如,HSQLDB, SELECT 1需要一个FROM子句)。

是否有一个数据库不可知的查询是等效的,但将适用于所有SQL数据库?

编辑:

如果没有(似乎是这种情况),有人可以build议一套SQL查询,将适用于各种数据库提供商? 我的意图是以编程方式确定我可以使用的基于我的数据库提供程序configuration的声明。

经过一些研究和一些答案的帮助:

SELECT 1

  • H2
  • MySQL的
  • Microsoft SQL Server(根据NimChimpsky )
  • PostgreSQL的
  • SQLite的

SELECT 1 FROM DUAL

  • 神谕

SELECT 1 FROM any_existing_table WHERE 1=0

要么

SELECT 1 FROM INFORMATION_SCHEMA.SYSTEM_USERS

  • HSQLDB(testing版本为1.8.0.10)

    注意:我尝试在第二个查询中使用WHERE 1=0子句,但它不能作为Apache Commons DBCP的validationQuery的值,因为查询不返回任何行


VALUES 1SELECT 1 FROM SYSIBM.SYSDUMMY1

  • Apache Derby(通过daiscog )

SELECT 1 FROM SYSIBM.SYSDUMMY1

  • DB2

select count(*) from systables

  • Informix的

如果您的驱动程序符合JDBC 4,则不需要专门的查询来testing连接。 而是有Connection.isValid来testing连接。

JDBC 4是2006年Java 6的一部分,你的驱动程序应该支持这个!

着名的连接池,如HikariCP,仍然有一个用于指定testing查询的configuration参数,但强烈不鼓励使用它:

🔠connectionTestQuery

如果你的驱动程序支持JDBC4,我们强烈build议不要设置这个属性。 这是针对不支持JDBC4 Connection.isValid()API的“传统”数据库。 这是在从池中给你一个连接之前执行的查询,用于validation与数据库的连接是否仍然存在。 再一次,尝试运行没有此属性的池,HikariCP将logging一个错误,如果你的驱动程序不是JDBC4兼容,让你知道。 默认值:无

不幸的是没有SELECT语句,不pipe数据库如何,它总能工作。

多数数据库支持:

 SELECT 1 

有些数据库不支持这个function,但是有一个名为DUAL的表格,当你不需要表格时可以使用它:

 SELECT 1 FROM DUAL 

MySQL也出于兼容性的原因支持这个function,但不是所有的数据库都支持。 对于不支持上述任何一种的数据库,解决方法是创build一个名为DUAL的包含单个行的表,然后上面的工作。

HSQLDB既不支持上述,也可以创buildDUAL表或者使用:

 SELECT 1 FROM any_table_that_you_know_exists_in_your_database 

我使用这个:

 select max(table_catalog) as x from information_schema.tables 

检查postgreSQL,MySQL和MSSQL的连接和运行查询的能力(结果为1行)。

对于使用select count(*)testing,使用select count(1)会更有效,因为*会导致它读取所有列数据。

select 1将在SQL Server中工作,不知道其他人。

使用标准的ansi sql来创build一个表,然后从该表中查询。

我用

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

为hsqldb 1.8.0

假设OP想要一个Java答案:

从JDBC3 / Java 6开始,应该使用isValid()方法,而不是创build自己的方法。

调用此方法ID时,驱动程序的实现者需要对数据库执行某种查询。 作为一个纯粹的JDBC用户,您不必知道或理解这个查询是什么。 您所要做的就是相信JDBC驱动程序的创build者已经正确地完成了自己的工作。

怎么样

 SELECT user() 

我用这个MySQL,H2还行,我不认识别人。

刚刚发现这是一个艰难的方式

 SELECT 1 FROM DUAL 

对于MaxDB也是如此。

我用这个火鸟

 select 1 from RDB$RELATION_FIELDS rows 1 

对于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