高效的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 1
或SELECT 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