Может ли кто-нибудь предложить хороший способ определить, пуста ли база данных из Java (должна поддерживать как минимум Microsoft SQL Server, Derby и Oracle)?
Под пустым я подразумеваю, что в состоянии было бы, если бы база данных была только что создана с новым оператором создания базы данных, хотя проверка не должна быть на 100% идеальной, если охватывает 99% случаев.
Первой моей мыслью было сделать что-то подобное ...
tables = metadata.getTables(null, null, null, null);
Boolean isEmpty = !tables.next();
return isEmpty;
... но, к сожалению, это дает мне кучу базовых системных таблиц (по крайней мере, в Microsoft SQL Server).




Вы всегда проверяете базы данных, созданные одинаково? Если это так, вы могли бы просто выбрать из подмножества таблиц, с которыми вы знакомы, для поиска данных.
Возможно, вам также придется беспокоиться о статических данных, которые, возможно, добавлены в таблицу поиска, которая на первый взгляд выглядит как «данные», но на самом деле может не быть «данными» в интересном смысле этого слова.
Можете ли вы предоставить дополнительную информацию о конкретной проблеме, которую вы пытаетесь решить? Интересно, можно ли с большим количеством данных дать более простой и надежный ответ.
Вы создаете эти базы данных?
Вы создаете их каждый раз примерно с одним и тем же конструктором?
Какой процесс заставляет этих ребят слоняться без дела и может ли этот конструктор разрушиться?
Конечно, существует процесс метаданных для циклического просмотра таблиц, просто может существовать что-то более нестандартное.
Существуют некоторые стандарты запросов схемы SQL-92 между базами данных - возможности для этого, конечно, варьируются в зависимости от поставщика.
SELECT COUNT(*) FROM [INFORMATION_SCHEMA].[TABLES] WHERE [TABLE_TYPE] = <tabletype>
Их поддержка зависит от поставщика, как и содержимое столбцов в представлении «Таблицы». Реализация документации по информационной схеме на языке SQL находится здесь:
http://msdn.microsoft.com/en-us/library/aa933204(SQL.80).aspx
В частности, в SQL Server метаданные sysobjects появились раньше инициативы стандартов SQL92.
SELECT COUNT(*) FROM [sysobjects] WHERE [type] = 'U'
Запрос выше возвращает количество пользовательских таблиц в базе данных. Подробнее о таблице sysobjects здесь:
http://msdn.microsoft.com/en-us/library/aa260447(SQL.80).aspx
Я не знаю, является ли это полным решением ... но вы можете определить, является ли таблица системной, прочитав столбец table_type в ResultSet, возвращаемом getTables:
int nonSystemTableCount = 0;
tables = metadata.getTables(null, null, null, null);
while( tables.next () ) {
if ( !"SYSTEM TABLE".equals( tables.getString( "table_type" ) ) ) {
nonSystemTableCount++;
}
}
boolean isEmpty = nonSystemTableCount == 0;
return isEmpty;
На практике ... Я думаю, вам, возможно, придется потрудиться, чтобы получить действительно надежное, действительно универсальное решение.
По крайней мере, в Oracle вы можете выбрать USER_TABLES, чтобы исключить любые системные таблицы.
Я не смог найти стандартного универсального решения, поэтому для каждой базы данных нужен собственный набор тестов.
Например, для Oracle я проверял таблицы, последовательности и индексы:
select count(*) from user_tables
select count(*) from user_sequences
select count(*) from user_indexes
Для SqlServer я использовал для проверки таблиц, представлений и хранимых процедур:
SELECT * FROM sys.all_objects where type_desc in ('USER_TABLE', 'SQL_STORED_PROCEDURE', 'VIEW')
Лучшее универсальное (и интуитивно понятное) решение, которое я получил, - использовать задачу ANT SQL - все, что мне нужно было сделать, это передать разные параметры для каждого типа базы данных.
т.е. файл сборки ANT выглядит так:
<project name = "run_sql_query" basedir = "." default = "main">
<!-- run_sql_query: -->
<target name = "run_sql_query">
<echo message = "=== running sql query from file ${database.src.file}; check the result in ${database.out.file} == = "/>
<sql classpath = "${jdbc.jar.file}"
driver = "${database.driver.class}"
url = "${database.url}"
userid = "${database.user}"
password = "${database.password}"
src = "${database.src.file}"
output = "${database.out.file}"
print = "yes"/>
</target>
<!-- Main: -->
<target name = "main" depends = "run_sql_query"/>
</project>
Для получения более подробной информации, пожалуйста, обратитесь к ANT:
По сути, я хочу убедиться, что база данных пуста, прежде чем я начну запускать процесс установки (чтобы защитить пользователей от случайного нацеливания на базу данных, которая уже содержит другие данные по ошибке). Возможно, возможно более простое решение, но я могу создать его сам, если нет хорошего универсального решения.