Spec-Zone .ru
спецификации, руководства, описания, API
|
Отметьте: MySQL и DB Java в настоящий момент не поддерживают определяемые пользователем типы. Следовательно, никакой учебный пример JDBC не доступен, чтобы демонстрировать функции, описанные в этом разделе.
Следующие темы затрагиваются:
SQL структурированные типы и DISTINCT
типы являются двумя типами данных, которые пользователь может определить в SQL. Они часто упоминаются как UDTs (определяемые пользователем типы), и Вы создаете их с SQL CREATE
TYPE
оператор.
Возвращаясь к примеру Перерыва на кофе, предположите, что владелец был успешен вне всех ожиданий и расширялся с новыми ответвлениями. Владелец решил добавить a STORES
таблица к базе данных, содержащей информацию о каждом установлении. STORES
будет иметь четыре столбца:
STORE_NO
для идентификационного номера каждого хранилищаLOCATION
для его адресаCOF_TYPES
для кофе это продаетMGR
для имени управляющего магазиномВладелец делает столбец LOCATION
будьте SQL структурированный тип, столбец COF_TYPES
SQL ARRAY
, и столбец MGR
a REF(MANAGER)
, с MANAGER
будучи SQL структурированный тип.
Первая вещь владелец должна определить новые структурированные типы для адреса и менеджера. SQL структурированный тип подобен структурированному, вводит язык программирования Java, в котором у этого есть элементы, названные атрибутами, которые могут быть любым типом данных. Владелец пишет следующий SQL-оператор, чтобы создать новый тип данных ADDRESS
:
CREATE TYPE ADDRESS ( NUM INTEGER, STREET VARCHAR(40), CITY VARCHAR(40), STATE CHAR(2), ZIP CHAR(5) );
В этом операторе, новом типе ADDRESS
имеет пять атрибутов, которые походят на поля в Java class. Атрибут NUM
INTEGER
, атрибут STREET
a VARCHAR(40)
, атрибут CITY
a VARCHAR(40)
, атрибут STATE
a CHAR(2)
, и атрибут ZIP
a CHAR(5)
.
Следующая выборка та, в который con
допустимое Connection
возразите, отправляет определение ADDRESS
к базе данных:
String createAddress = "CREATE TYPE ADDRESS " + "(NUM INTEGER, STREET VARCHAR(40), " + "CITY VARCHAR(40), STATE CHAR(2), ZIP CHAR(5))"; Statement stmt = con.createStatement(); stmt.executeUpdate(createAddress);
Теперь ADDRESS
структурированный тип регистрируется в базе данных как тип данных, и владелец может использовать это в качестве типа данных для столбца таблицы или атрибута структурированного типа.
Один из атрибутов владелец Перерыва на кофе планирует включать в новый структурированный тип MANAGER
номер телефона менеджера. Поскольку владелец будет всегда перечислять номер телефона как 10-разрядное число (чтобы убедиться, что он включает код области), и никогда не будет управлять этим как числом, владелец решает определить новый вызванный тип PHONE_NO
это состоит из 10 символов. Определение SQL этого типа данных, который может считаться структурированным типом только с одним атрибутом, похоже на это:
CREATE TYPE PHONE_NO AS CHAR(10);
Или, как отмечено ранее, для некоторых драйверов определение могло бы быть похожим на это:
CREATE DISTINCT TYPE PHONE_NO AS CHAR(10);
A DISTINCT
тип всегда основан на другом типе данных, который должен быть предварительно определенным типом. Другими словами, a DISTINCT
тип не может быть основан на определяемом пользователем типе (UDT). Получить или установить значение, которое является a DISTINCT
введите, используйте соответствующий метод для базового типа (тип, на котором это базируется). Например, чтобы получить экземпляр PHONE_NO
, который основан на a CHAR
введите, Вы использовали бы метод getString
потому что это - метод для того, чтобы получить a CHAR
.
Предположение, что значение типа PHONE_NO
находится в четвертом столбце текущей строки ResultSet
объект rs
, следующая строка кода получает это:
String phoneNumber = rs.getString(4);
Точно так же следующая строка кодовых наборов входной параметр, у которого есть тип PHONE_NO
для готового оператора, отправляемого базе данных:
pstmt.setString(1, phoneNumber);
Прибавляя к предыдущему фрагменту кода, определению PHONE_NO
будет отправлен базе данных со следующей строкой кода:
stmt.executeUpdate( "CREATE TYPE PHONE_NO AS CHAR(10)");
После регистрации типа PHONE_NO
с базой данных владелец может использовать это, поскольку столбец вводит таблицу или как тип данных для атрибута в структурированном типе. Определение MANAGER
в следующем использовании SQL-оператора PHONE_NO
как тип данных для атрибута PHONE
:
CREATE TYPE MANAGER ( MGR_ID INTEGER, LAST_NAME VARCHAR(40), FIRST_NAME VARCHAR(40), PHONE PHONE_NO );
Многократное использование stmt
, определенный ранее, следующий фрагмент кода отправляет определение структурированного типа MANAGER
к базе данных:
String createManager = "CREATE TYPE MANAGER " + "(MGR_ID INTEGER, LAST_NAME " + "VARCHAR(40), " + "FIRST_NAME VARCHAR(40), " + "PHONE PHONE_NO)"; stmt.executeUpdate(createManager);
Владелец Перерыва на кофе создал три новых типа данных, используемые в качестве типов столбца, или атрибут вводит базу данных: структурированные типы LOCATION
и MANAGER
, и DISTINCT
ввести PHONE_NO
. Предприниматель использовал PHONE_NO
как тип для атрибута PHONE
в новом типе MANAGER
, и ADDRESS
как тип данных для столбца LOCATION
в таблице STORES
. MANAGER
тип мог использоваться в качестве типа для столбца MGR
, но вместо этого предприниматель предпочитает использовать тип REF(MANAGER)
потому что предприниматель часто сделал, чтобы один человек управлял двумя или тремя хранилищами. Используя REF(MANAGER)
поскольку тип столбца избегает повторять все данные для MANAGER
когда один человек управляет больше чем одним хранилищем.
Со структурированным типом MANAGER
уже создаваемый, владелец может теперь составить таблицу, содержащую экземпляры MANAGER
на это можно сослаться. Ссылка на экземпляр MANAGER
будет иметь тип REF(MANAGER)
. SQL REF
не что иное как логический указатель на структурированный тип, таким образом, экземпляр REF(MANAGER)
служит логическим указателем на экземпляр MANAGER
.
Поскольку SQL REF
оцените должен быть постоянно связан с экземпляром структурированного типа, на который он ссылается, он сохранен в специальной таблице вместе с ее связанным экземпляром. Программист не создает REF
типы непосредственно, а скорее составляют таблицу, которая сохранит экземпляры определенного структурированного типа, на который можно сослаться. У каждого структурированного типа, на который нужно сослаться, будет своя собственная таблица. Когда Вы вставляете экземпляр структурированного типа в таблицу, база данных автоматически создает a REF
экземпляр. Например, чтобы содержать экземпляры MANAGER
на это можно сослаться, владелец, создаваемый следующая специальная таблица, используя SQL:
CREATE TABLE MANAGERS OF MANAGER (OID REF(MANAGER) VALUES ARE SYSTEM GENERATED);
Этот оператор составляет таблицу со специальным столбцом OID
, который хранит значения типа REF(MANAGER)
. Каждый раз экземпляр MANAGER
вставляется в таблицу, база данных генерирует экземпляр REF(MANAGER)
и сохраните это в столбце OID
. Неявно, дополнительный столбец хранит каждый атрибут MANAGER
это было вставлено в таблицу, также. Например, следующий фрагмент кода показывает как предприниматель, создаваемый три экземпляра MANAGER
структурированный тип, чтобы представить трех менеджеров:
INSERT INTO MANAGERS ( MGR_ID, LAST_NAME, FIRST_NAME, PHONE) VALUES ( 000001, 'MONTOYA', 'ALFREDO', '8317225600' ); INSERT INTO MANAGERS ( MGR_ID, LAST_NAME, FIRST_NAME, PHONE) VALUES ( 000002, 'HASKINS', 'MARGARET', '4084355600' ); INSERT INTO MANAGERS ( MGR_ID, LAST_NAME, FIRST_NAME, PHONE) VALUES ( 000003, 'CHEN', 'HELEN', '4153785600' );
Таблица MANAGERS
будет теперь иметь три строки, одну строку для каждого менеджера вставленными до сих пор. Столбец OID
будет содержать три уникальных объектных идентификатора типа REF(MANAGER)
, один для каждого экземпляра MANAGER.
Эти объектные идентификаторы были сгенерированы автоматически базой данных и будут постоянно сохранены в таблице MANAGERS
. Неявно, дополнительный столбец хранит каждый атрибут MANAGER
. Например, в таблице MANAGERS
, одна строка содержит a REF(MANAGER)
это ссылается на Альфредо Монтойя, другая строка содержит a REF(MANAGER)
это ссылается на Маргарет Хэскинс, и третья строка содержит a REF(MANAGER)
это ссылается на Хелен Чен.
К доступу a REF(MANAGER)
экземпляр, Вы выбираете это из его таблицы. Например, владелец, полученный ссылка на Альфредо Монтойя, Идентификационный номер которого 000001 со следующим фрагментом кода:
String selectMgr = "SELECT OID FROM MANAGERS " + "WHERE MGR_ID = 000001"; ResultSet rs = stmt.executeQuery(selectMgr); rs.next(); Ref manager = rs.getRef("OID");
Теперь переменная manager
может использоваться в качестве значения столбца, это ссылается на Альфредо Монтойя.
Следующий пример кода составляет таблицу MANAGERS
, таблица экземпляров структурированного типа MANAGER
на это можно сослаться, и вставляет три экземпляра MANAGER
в таблицу. Столбец OID
в этой таблице сохранит экземпляры REF(MANAGER)
. После того, как этот код выполняется, MANAGERS
таблица поссорится для каждого из трех MANAGER
объекты, вставленные, и значение в OID
столбец будет REF(MANAGER)
введите, который идентифицирует экземпляр MANAGER
сохраненный в той строке.
package com.oracle.tutorial.jdbc; import java.sql.*; public class CreateRef { public static void main(String args[]) { JDBCTutorialUtilities myJDBCTutorialUtilities; Connection myConnection = null; if (args[0] == null) { System.err.println("Properties file not specified " + "at command line"); return; } else { try { myJDBCTutorialUtilities = new JDBCTutorialUtilities(args[0]); } catch (Exception e) { System.err.println("Problem reading properties " + "file " + args[0]); e.printStackTrace(); return; } } Connection con = null; Statement stmt = null; try { String createManagers = "CREATE TABLE " + "MANAGERS OF MANAGER " + "(OID REF(MANAGER) " + "VALUES ARE SYSTEM " + "GENERATED)"; String insertManager1 = "INSERT INTO MANAGERS " + "(MGR_ID, LAST_NAME, " + "FIRST_NAME, PHONE) " + "VALUES " + "(000001, 'MONTOYA', " + "'ALFREDO', " + "'8317225600')"; String insertManager2 = "INSERT INTO MANAGERS " + "(MGR_ID, LAST_NAME, " + "FIRST_NAME, PHONE) " + "VALUES " + "(000002, 'HASKINS', " + "'MARGARET', " + "'4084355600')"; String insertManager3 = "INSERT INTO MANAGERS " + "(MGR_ID, LAST_NAME, " + "FIRST_NAME, PHONE) " + "VALUES " + "(000003, 'CHEN', 'HELEN', " + "'4153785600')"; con = myJDBCTutorialUtilities.getConnection(); con.setAutoCommit(false); stmt = con.createStatement(); stmt.executeUpdate(createManagers); stmt.addBatch(insertManager1); stmt.addBatch(insertManager2); stmt.addBatch(insertManager3); int [] updateCounts = stmt.executeBatch(); con.commit(); System.out.println("Update count for: "); for (int i = 0; i < updateCounts.length; i++) { System.out.print(" command " + (i + 1) + " = "); System.out.println(updateCounts[i]); } } catch(BatchUpdateException b) { System.err.println("-----BatchUpdateException-----"); System.err.println("Message: " + b.getMessage()); System.err.println("SQLState: " + b.getSQLState()); System.err.println("Vendor: " + b.getErrorCode()); System.err.print("Update counts for " + "successful commands: "); int [] rowsUpdated = b.getUpdateCounts(); for (int i = 0; i < rowsUpdated.length; i++) { System.err.print(rowsUpdated[i] + " "); } System.err.println(""); } catch(SQLException ex) { System.err.println("------SQLException------"); System.err.println("Error message: " + ex.getMessage()); System.err.println("SQLState: " + ex.getSQLState()); System.err.println("Vendor: " + ex.getErrorCode()); } finally { if (stmt != null) { stmt.close(); } JDBCTutorialUtilities.closeConnection(con); } } }
У нашего предпринимателя теперь есть UDTs, требуемый составлять таблицу STORES
. Структурированный тип ADDRESS
тип для столбца LOCATION
, и тип REF(MANAGER)
тип для столбца MGR
.
UDT COF_TYPES
основано на типе данных SQL ARRAY
и тип для столбца COF_TYPES
. Следующая строка кода создает тип COF_ARRAY
как ARRAY
значение с 10 элементами. Базовый тип COF_ARRAY
VARCHAR(40)
.
CREATE TYPE COF_ARRAY AS ARRAY(10) OF VARCHAR(40);
С новыми определенными типами данных следующий SQL-оператор составляет таблицу STORES
:
CREATE TABLE STORES ( STORE_NO INTEGER, LOCATION ADDRESS, COF_TYPES COF_ARRAY, MGR REF(MANAGER) );
Следующий фрагмент кода вставляет одну строку в STORES
таблица, предоставляя значения для столбцов STORE_NO
, LOCATION
, COF_TYPES
, и MGR
, в том порядке:
INSERT INTO STORES VALUES ( 100001, ADDRESS(888, 'Main_Street', 'Rancho_Alegre', 'CA', '94049'), COF_ARRAY('Colombian', 'French_Roast', 'Espresso', 'Colombian_Decaf', 'French_Roast_Decaf'), SELECT OID FROM MANAGERS WHERE MGR_ID = 000001 );
Следующее проходит через каждый столбец и значение, вставленное в это.
STORE_NO: 100001
Этот столбец является типом INTEGER
, и число 100001
INTEGER
введите, подобный записям, сделанным прежде в таблицах COFFEES
и SUPPLIERS
.
LOCATION: ADDRESS(888, 'Main_Street', 'Rancho_Alegre', 'CA', '94049')
Тип для этого столбца является структурированным типом ADDRESS
, и это значение является конструктором для экземпляра ADDRESS
. Когда мы отправили определение ADDRESS
был отправлен базе данных, одна из вещей, которые это сделало, состояла в том, чтобы создать конструктора для нового типа. Разделенные от запятой значения в круглых скобках являются значениями инициализации для атрибутов ADDRESS
введите, и они должны появиться в том же самом порядке, в котором атрибуты были перечислены в определении ADDRESS
ввести. 888
значение для атрибута NUM
, который является INTEGER
значение. "Main_Street"
значение для STREET
, и "Rancho_Alegre"
значение для CITY
, с обоими атрибутами, имеющими тип VARCHAR(40)
. Значение для атрибута STATE
"CA"
, который имеет тип CHAR(2)
, и значение для атрибута ZIP
"94049"
, который имеет тип CHAR(5)
.
COF_TYPES: COF_ARRAY( 'Colombian', 'French_Roast', 'Espresso', 'Colombian_Decaf', 'French_Roast_Decaf'),
Столбец COF_TYPES
имеет тип COF_ARRAY
с базовым типом VARCHAR(40)
, и разделенные от запятой значения между круглыми скобками String
объекты, которые являются элементами массива. Владелец, определенный тип COF_ARRAY
как наличие максимума 10 элементов. У этого массива есть 5 элементов потому что предприниматель, предоставленный только 5 String
объекты для этого.
MGR: SELECT OID FROM MANAGERS WHERE MGR_ID = 000001
Столбец MGR
тип REF(MANAGER)
, что означает, что значение в этом столбце должно быть ссылкой на структурированный тип MANAGER
. Все экземпляры MANAGER
сохранены в таблице MANAGERS
. Все экземпляры REF(MANAGER)
также сохранены в этой таблице, в столбце OID
. Менеджером по хранилищу, описанному в этой строке таблицы, является Альфредо Монтойя, и его информация хранится в экземпляре MANAGER
это имеет 100001
для атрибута MGR_ID
. Добраться REF(MANAGER)
экземпляр, связанный с MANAGER
объект для Альфредо Монтойя, выберите столбец OID
это находится в строке где MGR_ID
100001
в таблице MANAGERS
. Значение, которое будет сохранено в MGR
столбец STORES
таблица ( REF(MANAGER)
значение), значение DBMS, сгенерированный, чтобы однозначно определить этот экземпляр MANAGER
структурированный тип.
Отправьте предыдущий SQL-оператор базе данных со следующим фрагментом кода:
String insertMgr = "INSERT INTO STORES VALUES " + "(100001, " + "ADDRESS(888, 'Main_Street', " + "'Rancho_Alegre', 'CA', " + "'94049'), " + "COF_ARRAY('Colombian', " + "'French_Roast', 'Espresso', " + "'Colombian_Decaf', " + "'French_Roast_Decaf'}, " + "SELECT OID FROM MANAGERS " + "WHERE MGR_ID = 000001)"; stmt.executeUpdate(insertMgr);
Однако, потому что Вы собираетесь отправить несколько INSERT INTO
операторы, будет более эффективно отправить им всем вместе как пакетное обновление, как в следующем примере кода:
package com.oracle.tutorial.jdbc; import java.sql.*; public class InsertStores { public static void main(String args[]) { JDBCTutorialUtilities myJDBCTutorialUtilities; Connection myConnection = null; if (args[0] == null) { System.err.println( "Properties file " + "not specified " + "at command line"); return; } else { try { myJDBCTutorialUtilities = new JDBCTutorialUtilities(args[0]); } catch (Exception e) { System.err.println( "Problem reading " + "properties file " + args[0]); e.printStackTrace(); return; } } Connection con = null; Statement stmt = null; try { con = myJDBCTutorialUtilities.getConnection(); con.setAutoCommit(false); stmt = con.createStatement(); String insertStore1 = "INSERT INTO STORES VALUES (" + "100001, " + "ADDRESS(888, 'Main_Street', " + "'Rancho_Alegre', 'CA', " + "'94049'), " + "COF_ARRAY('Colombian', " + "'French_Roast', " + "'Espresso', " + "'Colombian_Decaf', " + "'French_Roast_Decaf'), " + "(SELECT OID FROM MANAGERS " + "WHERE MGR_ID = 000001))"; stmt.addBatch(insertStore1); String insertStore2 = "INSERT INTO STORES VALUES (" + "100002, " + "ADDRESS(1560, 'Alder', " + "'Ochos_Pinos', " + "'CA', '94049'), " + "COF_ARRAY('Colombian', " + "'French_Roast', " + "'Espresso', " + "'Colombian_Decaf', " + "'French_Roast_Decaf', " + "'Kona', 'Kona_Decaf'), " + "(SELECT OID FROM MANAGERS " + "WHERE MGR_ID = 000001))"; stmt.addBatch(insertStore2); String insertStore3 = "INSERT INTO STORES VALUES (" + "100003, " + "ADDRESS(4344, " + "'First_Street', " + "'Verona', " + "'CA', '94545'), " + "COF_ARRAY('Colombian', " + "'French_Roast', " + "'Espresso', " + "'Colombian_Decaf', " + "'French_Roast_Decaf', " + "'Kona', 'Kona_Decaf'), " + "(SELECT OID FROM MANAGERS " + "WHERE MGR_ID = 000002))"; stmt.addBatch(insertStore3); String insertStore4 = "INSERT INTO STORES VALUES (" + "100004, " + "ADDRESS(321, 'Sandy_Way', " + "'La_Playa', " + "'CA', '94544'), " + "COF_ARRAY('Colombian', " + "'French_Roast', " + "'Espresso', " + "'Colombian_Decaf', " + "'French_Roast_Decaf', " + "'Kona', 'Kona_Decaf'), " + "(SELECT OID FROM MANAGERS " + "WHERE MGR_ID = 000002))"; stmt.addBatch(insertStore4); String insertStore5 = "INSERT INTO STORES VALUES (" + "100005, " + "ADDRESS(1000, 'Clover_Road', " + "'Happyville', " + "'CA', '90566'), " + "COF_ARRAY('Colombian', " + "'French_Roast', " + "'Espresso', " + "'Colombian_Decaf', " + "'French_Roast_Decaf'), " + "(SELECT OID FROM MANAGERS " + "WHERE MGR_ID = 000003))"; stmt.addBatch(insertStore5); int [] updateCounts = stmt.executeBatch(); ResultSet rs = stmt.executeQuery( "SELECT * FROM STORES"); System.out.println("Table STORES after insertion:"); System.out.println("STORE_NO " + "LOCATION " + "COF_TYPE " + "MGR"); while (rs.next()) { int storeNo = rs.getInt("STORE_NO"); Struct location = (Struct)rs.getObject("LOCATION"); Object[] locAttrs = location.getAttributes(); Array coffeeTypes = rs.getArray("COF_TYPE"); String[] cofTypes = (String[])coffeeTypes.getArray(); Ref managerRef = rs.getRef("MGR"); PreparedStatement pstmt = con.prepareStatement( "SELECT MANAGER " + "FROM MANAGERS " + "WHERE OID = ?"); pstmt.setRef(1, managerRef); ResultSet rs2 = pstmt.executeQuery(); rs2.next(); Struct manager = (Struct)rs2.getObject("MANAGER"); Object[] manAttrs = manager.getAttributes(); System.out.print(storeNo + " "); System.out.print( locAttrs[0] + " " + locAttrs[1] + " " + locAttrs[2] + ", " + locAttrs[3] + " " + locAttrs[4] + " "); for (int i = 0; i < cofTypes.length; i++) System.out.print( cofTypes[i] + " "); System.out.println( manAttrs[1] + ", " + manAttrs[2]); rs2.close(); pstmt.close(); } rs.close(); } catch(BatchUpdateException b) { System.err.println("-----BatchUpdateException-----"); System.err.println("SQLState: " + b.getSQLState()); System.err.println("Message: " + b.getMessage()); System.err.println("Vendor: " + b.getErrorCode()); System.err.print("Update counts: "); int [] updateCounts = b.getUpdateCounts(); for (int i = 0; i < updateCounts.length; i++) { System.err.print(updateCounts[i] + " "); } System.err.println(""); } catch(SQLException ex) { System.err.println("SQLException: " + ex.getMessage()); System.err.println("SQLState: " + ex.getSQLState()); System.err.println("Message: " + ex.getMessage()); System.err.println("Vendor: " + ex.getErrorCode()); } finally { if (stmt != null) { stmt.close(); } JDBCTutorialUtilities.closeConnection(con); } } } }