Эффективный SQL-запрос или запрос проверки, который будет работать во всех (или большинстве) базах данных

Многие библиотеки пула соединений с базой данных предоставляют возможность протестировать свои SQL-соединения для праздности. Например, библиотека пула JDBC c3p0 имеет свойство preferredTestQuery, который запускается при соединении с заданными интервалами. Аналогично, DBCP Apache Commons validationQuery.

Многие пример запросы Я видел для MySQL и рекомендуется использовать SELECT 1; как значение для тестового запроса. Однако этот запрос не работает в некоторых базах данных (например, HSQLDB, для которого SELECT 1 ожидает предложение FROM).

Есть ли агрегированный запрос базы данных, который эквивалентно эффективен, но будет работать для всех баз данных SQL?

Edit:

Если нет (похоже, это так), может ли кто-нибудь предложить набор SQL-запросов, которые будут работать для разных поставщиков баз данных? Мое намерение состояло в том, чтобы программно определить оператор, который я могу использовать на основе конфигурации поставщика базы данных.

Ответ 1

После небольшого исследования вместе с помощью некоторых из ответов здесь:

SELECT 1

  • Н2
  • 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 DBCP validationQuery, так как запрос не возвращает никаких строк


VALUES 1 или SELECT 1 FROM SYSIBM.SYSDUMMY1

  • Apache Derby (через daiscog)

SELECT 1 FROM SYSIBM.SYSDUMMY1

  • DB2

select count(*) from systables

  • Informix

Ответ 2

Если ваш драйвер совместим с JDBC 4, нет необходимости в специальном запросе для проверки соединений. Вместо этого Connection.isValid проверить соединение.

JDBC 4 является частью Java 6 с 2006 года, и вы должны поддержать это сейчас!

Известные пулы соединений, такие как HikariCP, все еще имеют параметр конфигурации для указания тестового запроса, но сильно не рекомендуют его использовать:

🔠СоединениеTestQuery

Если ваш драйвер поддерживает JDBC4, мы сильно не рекомендуется устанавливать это свойство. Это для "устаревших" баз данных которые не поддерживают API JDBC4 Connection.isValid(). Это запрос, который будет выполнен непосредственно перед тем, как вам будет дано соединение из пула, чтобы проверить, что соединение с базой данных по-прежнему в живых. Опять же, попробуйте запустить пул без этого свойства, HikariCP будет регистрировать ошибку, если ваш драйвер не совместим с JDBC4, чтобы вы могли знать. По умолчанию: none

Ответ 3

К сожалению, нет инструкции SELECT, которая всегда будет работать независимо от базы данных.

Поддержка большинства:

SELECT 1

Некоторые базы данных не поддерживают это, но имеют таблицу DUAL, которую вы можете использовать, когда вам не нужна таблица:

SELECT 1 FROM DUAL

MySQL также поддерживает это по соображениям совместимости, но не все базы данных. Обходной путь для баз данных, которые не поддерживают ни одно из вышеперечисленных, заключается в создании таблицы с именем DUAL, содержащей одну строку, тогда выше будет работать.

HSQLDB не поддерживает ни то, ни другое, поэтому вы можете создать таблицу DUAL или использовать:

SELECT 1 FROM any_table_that_you_know_exists_in_your_database

Ответ 4

Я использую этот:

select max(table_catalog) as x from information_schema.tables

чтобы проверить соединение и возможность запуска запросов (с 1 строкой в ​​результате) для postgreSQL, MySQL и MSSQL.

Ответ 5

Для тестов, использующих select count(*), более эффективно использовать select count(1), потому что * может заставить его прочитать все данные столбца.

Ответ 6

select 1 будет работать на сервере sql, но не уверен в других.

Используйте стандартный ansi sql для создания таблицы, а затем запроса из этой таблицы.

Ответ 7

Я использую

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

для hsqldb 1.8.0

Ответ 8

Предполагая, что OP хочет получить ответ Java:

По состоянию на JDBC3/Java 6 существует isValid() метод, который следует использовать, а не изобретать собственный метод.

Разработчик драйвера должен выполнять какой-то запрос к базе данных при вызове этого метода. Вы - как простой пользователь JDBC - не должны знать или понимать, что это за запрос. Все, что вам нужно сделать, - это доверять тому, что создатель драйвера JDBC правильно выполнил свою работу.

Ответ 9

Как насчет

SELECT user()

Я использую это before.MySQL, H2 в порядке, я не знаю других.

Ответ 10

Просто узнал, что он

SELECT 1 FROM DUAL

для MaxDB.

Ответ 11

Я использую это для Firebird

select 1 from RDB$RELATION_FIELDS rows 1

Ответ 12

Для 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