Эффективный тестовый запрос SQL или запрос проверки, который будет работать во всех (или большинстве) баз данных
многие библиотеки пулов соединений с базами данных предоставляют возможность тестировать свои SQL-соединения на бездействие. Например, библиотека пулов JDBC c3p0 есть свойство под названием preferredTestQuery, который выполняется на соединении с заданными интервалами. Аналогично, Apache Commons DBCP имеет validationQuery.
много примерзапросы Я видел для MySQL и рекомендую использовать SELECT 1; Как значение для тестовый запрос. Однако этот запрос не работает на некоторых базах данных (например, HSQLDB, для которых SELECT 1 ждет FROM предложения).
есть ли база данных-агностический запрос, который эквивалентно эффективен, но будет работать для всех баз данных SQL?
Edit:
если нет (что, кажется, так), может ли кто-нибудь предложить набор SQL-запросов, которые будут работать для различных поставщиков баз данных? Мое намерение состояло бы в том, чтобы программно определить оператор, который я могу использовать на основе конфигурации поставщика базы данных.
12 ответов:
после небольшого исследования вместе с помощью некоторых ответов здесь:
SELECT 1
- H2
- MySQL
- Microsoft SQL Server (согласно NimChimpsky)
- PostgreSQL
- SQLite
SELECT 1 FROM DUAL
- Oracle
SELECT 1 FROM any_existing_table WHERE 1=0или
SELECT 1 FROM INFORMATION_SCHEMA.SYSTEM_USERS
HSQLDB (проверено с версией 1.8.0.10)
Примечание: я пробовал использовать
WHERE 1=0предложение по второму запросу, но оно не работает как значение для Apache Commons DBCPvalidationQuery, так как запрос не возвращает никаких строк
VALUES 1илиSELECT 1 FROM SYSIBM.SYSDUMMY1
- Apache Derby (via daiscog)
SELECT 1 FROM SYSIBM.SYSDUMMY1
- DB2
select count(*) from systables
- Informix
Если ваш драйвер совместим с JDBC 4, нет необходимости в выделенном запросе для проверки соединений. Вместо этого есть подключение.isValid для проверки соединения.
JDBC 4 является частью Java 6 с 2006 года, и вы драйвер должен поддерживать это сейчас!
известные пулы соединений, такие как HikariCP, все еще имеют параметр конфигурации для указания тестового запроса, но настоятельно не рекомендуют его использовать:
connectionTestQuery
Если ваш драйвер поддерживает JDBC4 мы сильно не рекомендуется устанавливать это свойство. Это для" устаревших " баз данных это не поддерживает соединение JDBC4.функция IsValid() API-интерфейс. Это запрос, который будет выполнен непосредственно перед подключением к вам из пула, чтобы проверить, что подключение к базе данных по-прежнему живой. Опять же, попробуйте запустить бассейн без этого свойства, HikariCP будет регистрироваться ошибка, если ваш драйвер не соответствует JDBC4, чтобы позволить вам знать. По умолчанию: нет
к сожалению, нет оператора SELECT, который всегда будет работать независимо от базы данных.
большинство поддержка баз данных:
SELECT 1некоторые базы данных не поддерживают это, но имеют таблицу с именем DUAL, которую вы можете использовать, когда вам не нужна таблица:
SELECT 1 FROM DUALMySQL также поддерживает это по соображениям совместимости, но не все базы данных делают. Обходным путем для баз данных, которые не поддерживают ни одно из вышеперечисленных, является создание таблицы с именем DUAL который содержит одну строку, то выше будет работать.
HSQLDB не поддерживает ни одно из вышеперечисленных, поэтому вы можете либо создать двойную таблицу, либо использовать:
SELECT 1 FROM any_table_that_you_know_exists_in_your_database
Я использую этот:
select max(table_catalog) as x from information_schema.tablesчтобы проверить соединение и возможность выполнения запросов (с 1 строкой в результате) для postgreSQL, MySQL и MSSQL.
для тестов с помощью
select count(*), Он должен быть более эффективным в использованииselect count(1), потому что*может заставить его прочитать все данные столбца.
select 1будет работать в sql server, не уверен в других.используйте стандартный ANSI sql для создания таблицы, а затем запрос из этой таблицы.
предполагая, что OP хочет получить ответ Java:
с JDBC3 / Java 6 есть isValid () метод, который следует использовать, а не изобретать свой собственный метод.
разработчик драйвера должен выполнить какой-то запрос к базе данных при вызове этого идентификатора метода. Вы-как простой пользователь JDBC-не должны знать или понимать, что это за запрос. Все, что вам нужно сделать, это верить, что создатель драйвера JDBC сделал его/ее работать правильно.
на 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
Comments