Этот раздел объясняет, как работать с результатами обработки.
Все операции по базе данных возвращают результат. Тип возвращенного результата зависит от операции, которая была выполнена. Различные типы возвращенных результатов обрисованы в общих чертах в следующей таблице.
Класс результата |
Возвращен |
Обеспечивает |
---|---|---|
|
|
|
|
|
|
|
|
Принесенный набор данных |
|
|
Принесенный набор данных |
Следующая диаграмма классов дает основной обзор обработки результата.
Рис. 9.1. Диаграмма классов
AUTO-INCREMENT
Общая задача MySQL состоит в том, чтобы использовать столбцы
AUTO_INCREMENT
, например производя значения
первичного ключа. Эта секция объясняет, как восстановить значения
AUTO_INCREMENT
, добавляя строки через X DevAPI.
Для большего количества справочной информации посмотрите
Using AUTO_INCREMENT. X DevAPI предоставляет следующие
методы, чтобы возвратить значение столбцов
AUTO_INCREMENT
от возвращаемого значения
table.insert():
getFirstAutoIncrementValue()
getAutoIncrementValues()
В следующих примерах предполагается, что таблица содержит столбец
для которого атрибут AUTO_INCREMENT
установлен.
Кроме того, предполагается, что все вставки имеют успех. Функция
getFirstAutoIncrementValue()
используется, добавляя строки индивидуально, или другими словами не
формируя цепочку вызовов table.insert()
:
res = tab.insert(['name']).values('Sakila'}.execute(); print(res.getFirstAutoIncrementValue());
Когда вы связываете много вызовов
table.insert()
,
там потенциально будут возвращены многократные значения
AUTO_INCREMENT
. Функция
getAutoIncrementValues()
возвращает список из
всех значений AUTO_INCREMENT
,
вставляя многократные строки:
res = tab.insert(['name']).values('Sakila').values('Otto').execute(); print(res.getAutoIncrementValues()); // prints a list of values for 'Sakila' and 'Otto'
Отметьте, что столбцы AUTO_INCREMENT
могут использоваться для создания первичного ключа или значений
id
, но не ограничиваются ими.
Операции, которые приносят элементы данных, возвращают набор данных в
противоположность операциям, которые изменяют данные и возвращают набор
результатов. Элементы данных могут быть прочитаны из базы данных через
Collection.find()
,
Table.select()
и
Session.sql()
.
Все три метода возвращают наборы данных, которые заключают в капсулу элементы
данных. Collection.find()
возвращает набор данных с документами, а
Table.select()
и
Session.sql()
возвратят набор
данных со строками.
Все наборы данных осуществляют единый способ повторить их элементы данных.
Объединенный синтаксис получения элементов поштучно, используя
fetchOne()
или всего списка через
fetchAll()
.
fetchOne()
и
fetchAll()
используют итеративную семантику
"только вперед". Соединители, реализующие X DevAPI, могут предложить более
продвинутые итеративные образцы, чтобы соответствовать общим
образцам соответствующего языка.
Следующий пример показывает, как получить доступ к документам,
возвращенным Collection.find()
при помощи fetchOne()
при проходе
по всем документам.
Первый вызов fetchOne()
возвращает первый
найденный документ. Все последующие увеличивают внутренний элемент данных
на одну позицию и возвращают найденный элемент. Когда последний элемент
данных был прочитан и fetchOne()
вызван
снова, вернется NULL.
Используя fetchOne()
невозможно
переустановить внутренний курсор элемента данных к первому элементу данных,
чтобы начать читать элементы данных снова. Элемент данных это Document,
который был принесен однажды с использованием
fetchOne()
. Время жизни элемента данных
отделено от набора данных. Перспективные пункты потребляются вызывающим
по мере поступления. Этот пример предполагает, что
испытательная схема существует.
MySQL Shell JavaScript Code
var myColl = db.getCollection('my_collection'); var res = myColl.find('name like :name').bind('name','S%').execute(); var doc; while (doc = res.fetchOne()) { print(doc); }
MySQL Shell Python Code
myColl = db.get_collection('my_collection') res = myColl.find('name like :name').bind('name','S%').execute() doc = res.fetch_one() while doc: print(doc) doc = res.fetch_one()
C# Code
var myColl = db.GetCollection("my_collection"); var res = myColl.Find("name like :name").Bind("name", "S%").Execute(); DbDoc doc; while ((doc = res.FetchOne()) != null) { Console.WriteLine(doc); }
Python Code
my_coll = my_schema.get_collection('my_collection') res = my_coll.find('name like :name').bind('name', 'S%').execute() doc = res.fetch_one() while doc: print(doc) doc = res.fetch_one()
Java Code
Collection myColl = db.getCollection("my_collection"); DocResult res = myColl.find("name like :name").bind("name", "S%").execute(); DbDoc doc; while ((doc = res.fetchOne()) != null) { System.out.println(doc); }
C++ Code
Collection myColl = db.getCollection("my_collection"); DocResult res = myColl.find("name like :name").bind("name", "S%").execute(); DbDoc doc; while ((doc = res.fetchOne())) { cout << doc <<endl; }
Node.js JavaScript Code
var myColl = db.getCollection('my_collection'); myColl.find('name like :name').bind('name', 'S%').execute().then(res => { while (doc = res.fetchOne()) { console.log(doc); } }); myColl.find('name like :name').bind('name', 'S%'). execute(function (doc) { console.log(doc); });
Результаты могут также быть возвращены функции обратного вызова, которая
передается к execute()
асинхронным
способом каждый раз, когда сервер передает результаты.
Node.js JavaScript Code
var myColl = db.getCollection('my_collection'); myColl.find('name like :name').bind('name', 'S%'). execute(function (doc) { console.log(doc); });
Следующий пример показывает, как непосредственно получить доступ к
строкам, возвращенным Table.select()
.
Образец кода для повторения результата тот же. Различие между следующим и
предыдущим примером в обработке элемента данных. Здесь
fetchOne()
вернет Rows.
Точный синтаксис, чтобы получить доступ к значениям столбцов Row зависит от
языка. Пример предполагает, что испытательная схема существует, и что список
сотрудников существует в myTable.
MySQL Shell JavaScript Code
var myRows = myTable.select(['name', 'age']). where('name like :name').bind('name','S%').execute(); var row; while (row = myRows.fetchOne()) { // Accessing the fields by array print('Name: ' + row['name'] + '\n'); // Accessing the fields by dynamic attribute print(' Age: ' + row.age + '\n'); }
MySQL Shell Python Code
myRows = myTable.select(['name', 'age']).where('name like :name'). bind('name','S%').execute() row = myRows.fetch_one() while row: # Accessing the fields by array print('Name: %s\n' % row[0]) # Accessing the fields by dynamic attribute print('Age: %s\n' % row.age) row = myRows.fetch_one()
Node.js JavaScript Code
var myRows = myTable.select(['name', 'age']).where('name like :name'). bind('name','S%').execute(function (row) { // Connector/Node.js does not support referring to row columns by their name yet. // One needs to access fields by their array index. console.log('Name: ' + row[0]); console.log(' Age: ' + row[1]); });
C# Code
var myRows = myTable.Select("name", "age").Where("name like :name"). Bind("name", "S%").Execute(); Row row; while ((row = myRows.FetchOne()) != null) { // Accessing the fields by array Console.WriteLine("Name: " + row[0]); // Accessing the fields by name Console.WriteLine("Age: " + row["age"]); }
Python Code
rows = my_table.select(['name', 'age']).where('name like :name'). bind('name','S%').execute() row = rows.fetch_one() while row: # Accessing the fields by array print('Name: {0}'.format(row[0])) # Accessing the fields by dynamic attribute print('Age: {0}'.format(row['age']) row = rows.fetch_one()
Java Code
RowResult myRows = myTable.select("name, age").where("name like :name"). bind("name", "S%").execute(); Row row; while ((row = myRows.fetchOne()) != null) { // Accessing the fields System.out.println(" Age: " + row.getInt("age") + "\n"); }
C++ Code
RowResult myRows = myTable.select("name", "age").where("name like :name"). bind("name", "S%").execute(); Row row; while ((row = myRows.fetchOne())) { // Connector/C++ does not support referring to row columns by their name yet. cout <<"Name: " << row[0] <<endl; cout <<" Age: " << row[1] <<endl; int age = row[1]; // One needs explicit .get<int>() as otherwise operator<() is ambiguous bool youth = row[age].get<int>() < 18; // Alternative formulation bool youth = (int)row[age] < 18; }
В дополнение к образцу использования
fetchOne()
, изученному в
разделе 9.3,
который позволяет запросам потреблять элементы данных поштучно, X DevAPI
также обеспечивает использование образца
fetchAll()
, который передает все элементы данных
из набора данных как список. Разные реализации X DevAPI
используют соответствующие типы данных для своего языка программирования для
списка. Поскольку различные типы данных используются, родные конструкции
языка поддерживаются, чтобы получить доступ к элементам списка.
Следующий пример предполагает, что испытательная схема существует, и что
список сотрудников существует в myTable.
MySQL Shell JavaScript Code
var myResult = myTable.select(['name', 'age']). where('name like :name').bind('name','S%').execute(); var myRows = myResult.fetchAll(); for (index in myRows) { print (myRows[index].name + " is " + myRows[index].age + " years old."); }
MySQL Shell Python Code
myResult = myTable.select(['name', 'age']) \ .where('name like :name').bind('name','S%') \ .execute() myRows = myResult.fetch_all() for row in myRows: print("%s is %s years old." % (row.name, row.age))
Node.js JavaScript Code
myTable.select(['name', 'age']) .where('name like :name') .bind('name', 'S%').execute() .then(myResult => { var myRows = myResult.fetchAll(); myRows.forEach(row => { console.log(`${row[0]} is ${row[1]} years old.`); }); });
C# Code
var myRows = myTable.Select("name", "age") .Where("name like :name").Bind("name", "S%") .Execute(); var rows = myRows.FetchAll();
Python Code
result = myTable.select(['name', 'age']) \ .where('name like :name').bind('name', 'S%') \ .execute() rows = result.fetch_all() for row in rows: print("{0} is {1} years old.".format(row["name"], row["age"]))
Java Code
RowResult myRows = myTable.select("name, age") .where("name like :name").bind("name", "S%") .execute(); List<Row> rows = myRows.fetchAll(); for (Row row : rows) { // Accessing the fields System.out.println(" Age: " + row.getInt("age") + "\n"); }
C++ Code
RowResult myRows = myTable.select("name, age") .where("name like :name") .bind("name", "S%") .execute(); std::list<Row> rows = myRows.fetchAll(); for (Row row : rows) { cout << row[1] << endl; } // Directly iterate over rows, without stroing them in a container for (Row row : myRows.fetchAll()) { cout << row[1] << endl; }
Смешивая fetchOne()
и
fetchAll()
, чтобы читать из одного набора
данных, имейте в виду, что каждый вызов
fetchOne()
или
fetchAll()
потребляет возвращенные элементы
данных. Использованные элементы нельзя затребовать снова. Если, например,
приложение вызывает fetchOne()
, чтобы получить
первый элемент из набора данных, затем
fetchAll()
вернет элементы от второго до
последнего. Первый элемент не часть списка элементов данных, возвращенных
fetchAll()
. Точно так же, вызывая
fetchAll()
снова для набора данных после запроса
его ранее, второй вызов возвращает пустую коллекцию.
Использование fetchAll()
вынуждает
Connector построить список всех пунктов в памяти, прежде чем список в целом
сможет быть передан приложению. Время жизни списка независимо от жизни набора
данных, который произвел его.
Асинхронное выполнение запроса работает с момента запроса и до получения
любого ответа от сервера. Запрос fetchAll()
,
чтобы прочитать элементы данных, произведенные асинхронным выполнением
запроса, может заблокировать вызывающего.
fetchAll()
не может вернуть управление прежде,
чем закончит чтение результатов с сервера.
Когда вы выполняете операцию SQL в сессии, используя метод
sql()
, вернется SqlResult.
Повторение SqlResult идентично работе с результатами операций CRUD.
Следующий пример предполагает, что пользовательская таблица существует.
MySQL Shell JavaScript Code
var res = mySession.sql('SELECT name, age FROM users').execute(); var row; while (row = res.fetchOne()) { print('Name: ' + row['name'] + '\n'); print(' Age: ' + row.age + '\n'); }
MySQL Shell Python Code
res = mySession.sql('SELECT name, age FROM users').execute() row = res.fetch_one() while row: print('Name: %s\n' % row[0]) print(' Age: %s\n' % row.age) row = res.fetch_one()
Node.js JavaScript Code
mySession.sql('SELECT name, age FROM users') .execute() .then(res => { while (row = res.fetchOne()) { console.log('Name: ' + row[0] + '\n'); console.log(' Age: ' + row[1] + '\n'); } }); // Alternatively, you can use callbacks session.sql('SELECT name, age FROM users').execute(function (row) { console.log('Name: ' + row[0] + '\n'); console.log(' Age: ' + row[1] + '\n'); });
C# Code
var res = Session.SQL("SELECT name, age FROM users").Execute(); while (res.Next()) { Console.WriteLine("Name: " + res.Current["name"]); Console.WriteLine("Age: " + res.Current["age"]); }
Python Code
# Connector/Python res = mySession.sql('SELECT name, age FROM users').execute() row = res.fetch_one() while row: print('Name: %s\n' % row[0]) print(' Age: %s\n' % row.age) row = res.fetch_one()
Java Code
SqlResult res = mySession.sql("SELECT name, age FROM users").execute(); Row row; while ((row = res.fetchOne()) != null) { System.out.println(" Name: " + row.getString("name") + "\n"); System.out.println(" Age: " + row.getInt("age") + "\n"); }
C++ Code
RowResult res = mysession.sql("SELECT name, age FROM users").execute(); Row row; while ((row = res.fetchOne())) { cout << "Name: " << row[0] << endl; cout << " Age: " << row[1] << endl; }
SqlResult отличается от результатов, возвращенных операциями CRUD тем, как
представляются наборы результатов и наборы данных. SqlResult объединяет набор
результатов, произведенный, например,
INSERT
и набор данных, произведенный,
например, SELECT
.
В отличие от этого, с операциями CRUD между двумя типами нет никакого
различия. SqlResult экспортирует методы для доступа к данным и получения
последнего вставленного id или количества затронутых строк.
Используйте метод hasData()
, чтобы понять,
является ли SqlResult набором данных или результатом. Метод полезен, когда
должен быть написан код, который не знает о происхождении SqlResult.
Это может иметь место, сочиняя функцию универсального приложения, чтобы
напечатать результаты запроса или обрабатывая результаты хранимой процедуры.
Если hasData()
вернет true, SqlResult происходит
из
SELECT
или подобной команды, которая
может возвратить строки.
Возвращаемое значение true не указывает, содержит ли набор данных
какие-либо строки. Набор данных может быть пустым, например это пусто, если
fetchOne()
вернет NULL или
fetchAll()
вернет пустой список.
Следующий пример предполагает, что процедура
my_proc
существует.
MySQL Shell JavaScript Code
var res = mySession.sql('CALL my_proc()').execute(); if (res.hasData()) { var row = res.fetchOne(); if (row) { print('List of row available for fetching.'); do { print(row); } while (row = res.fetchOne()); } else { print('Empty list of rows.'); } } else { print('No row result.'); }
MySQL Shell Python Code
res = mySession.sql('CALL my_proc()').execute() if res.has_data(): row = res.fetch_one() if row: print('List of row available for fetching.') while row: print(row) row = res.fetch_one() else: print('Empty list of rows.') else: print('No row result.')
Node.js JavaScript Code
mySession.sql('CALL my_proc()') .execute() .then(function (res) { if (!res.hasData()) { return console.log('No row result.'); } var row = res.fetchOne(); if (!row) { console.log('Empty list of rows.'); } console.log('List of row available for fetching.'); do { console.log(row); } while (row = res.fetchOne()); })
C# Code
var res = Session.SQL("CALL my_proc()").Execute(); if (res.HasData) { var row = res.FetchOne(); if (row != null) { Console.WriteLine("List of row available for fetching."); do { PrintResult(row); } while ((row = res.FetchOne()) != null); } else { Console.WriteLine("Empty list of rows."); } } else { Console.WriteLine("No row result."); }
Python Code
# Connector/Python res = mySession.sql('CALL my_proc()').execute() if res.has_data(): row = res.fetch_one() if row: print('List of row available for fetching.') while row: print(row) row = res.fetch_one() else: print('Empty list of rows.') else: print('No row result.')
Java Code
SqlResult res = mySession.sql("CALL my_proc()").execute(); if (res.hasData()) { Row row = res.fetchOne(); if (row != null) { System.out.println("List of rows available for fetching."); do { for (int c = 0; c < res.getColumnCount(); c++) { System.out.println(row.getString(c)); } } while ((row = res.fetchOne()) != null); } else { System.out.println("Empty list of rows."); } } else { System.out.println("No row result."); }
C++ Code
SqlResult res = mysession.sql("CALL my_proc()").execute(); if (res.hasData()) { Row row = res.fetchOne(); if (row) { cout << "List of row available for fetching." << endl; do { cout << "next row: "; for (unsigned i=0 ; i < row.colCount(); ++i) cout << row[i] << ", "; cout << endl; } while ((row = res.fetchOne())); } else { cout << "Empty list of rows." << endl; } } else { cout << "No row result." << endl; }
Неправильно вызывать fetchOne()
или
fetchAll()
, когда
hasResult()
указывает, что SqlResult это
не набор данных.
MySQL Shell JavaScript Code
function print_result(res) { if (res.hasData()) { // SELECT var columns = res.getColumns(); var record = res.fetchOne(); while (record) { for (index in columns) { print (columns[index].getColumnName() + ": " + record[index]+"\n"); } // Get the next record record = res.fetchOne(); } } else { // INSERT, UPDATE, DELETE, ... print('Rows affected: ' + res.getAffectedRowCount()); } } print_result(mySession.sql('DELETE FROM users WHERE age < 18').execute()); print_result(mySession.sql('SELECT * FROM users WHERE age = 40').execute());
MySQL Shell Python Code
def print_result(res): if res.has_data(): # SELECT columns = res.get_columns() record = res.fetch_one() while record: index = 0 for column in columns: print("%s: %s \n" % (column.get_column_name(), record[index])) index = index + 1 # Get the next record record = res.fetch_one() else: #INSERT, UPDATE, DELETE, ... print('Rows affected: %s' % res.get_affected_items_count()) print_result(mySession.sql('DELETE FROM users WHERE age < 18').execute()) print_result(mySession.sql('SELECT * FROM users WHERE age = 40').execute())
Node.js JavaScript Code
function print_result(res) { if (res.hasData()) { // SELECT var columns = res.getColumns(); var record = res.fetchOne(); while (record) { for (index in columns) { console.log(columns[index].getColumnName() + ": " + record[index]); } // Get the next record record = res.fetchOne(); } } else { // INSERT, UPDATE, DELETE, ... console.log('Rows affected: ' + res.getAffectedRowsCount()); } } mySession.sql(`DELETE FROM users WHERE age < 18`) .execute() .then(function (res) { print_result(res); }); mySession.sql(`SELECT * FROM users WHERE age = 40`) .execute() .then(function (res) { print_result(res); });
C# Code
private void print_result(SqlResult res) { if (res.HasData) { // SELECT } else { // INSERT, UPDATE, DELETE, ... Console.WriteLine("Rows affected: " + res.RecordsAffected); } } print_result(Session.SQL("DELETE FROM users WHERE age < 18").Execute()); print_result(Session.SQL("SELECT COUNT(*) AS forty FROM users WHERE age = 40").Execute());
Python Code
# Connector/Python def print_result(res): if res.has_data(): # SELECT columns = res.get_columns() record = res.fetch_one() while record: index = 0 for column in columns: print("%s: %s \n" % (column.get_column_name(), record[index])) index = index + 1 # Get the next record record = res.fetch_one() else: #INSERT, UPDATE, DELETE, ... print('Rows affected: %s' % res.get_affected_items_count()) print_result(mySession.sql('DELETE FROM users WHERE age < 18').execute()) print_result(mySession.sql('SELECT * FROM users WHERE age = 40').execute())
Java Code
private void print_result(SqlResult res) { if (res.hasData()) { // SELECT Row row; while ((row = res.fetchOne()) != null) { for (int c = 0; c < res.getColumnCount(); c++) { System.out.println(row.getString(c)); } } } else { // INSERT, UPDATE, DELETE, ... System.out.println("Rows affected: " + res.getAffectedItemsCount()); } } print_result(mySession.sql("DELETE FROM users WHERE age < 18").execute()); print_result(mySession.sql("SELECT COUNT(*) AS forty FROM users WHERE age = 40").execute());
C++ Code
void print_result(SqlResult &&_res) { // Note: We need to store the result somewhere to be able to process it. SqlResult res(std::move(_res)); if (res.hasData()) { // SELECT const Columns &columns = res.getColumns(); Row record = res.fetchOne(); while (record) { for (unsigned index=0; index < res.getColumnCount(); ++index) { cout << columns[index].getColumnName() << ": " << record[index] << endl; } // Get the next record record = res.fetchOne(); } } else { // INSERT, UPDATE, DELETE, ... // Note: getAffectedRowCount() not yet implemented in Connector/C++. cout << "No rows in the result" << endl; } } print_result(mysession.sql("DELETE FROM users WHERE age < 18").execute()); print_result(mysession.sql("SELECT * FROM users WHERE age = 40").execute());
Запрос хранимой процедуры мог бы привести к необходимости иметь дело с
многократными наборами результатов как часть единственного выполнения.
В результате для выполнения запросов возвращен объект SqlResult, который
заключает в капсулу первый набор результатов. После обработки набора
результатов можно вызвать nextResult()
, чтобы
продвигаться к следующему результату, если таковой имеется. Как только вы
продвинулись к следующему набору результатов, он заменяет ранее загруженный
результат, который становится недоступным.
MySQL Shell JavaScript Code
function print_result(res) { if (res.hasData()) { // SELECT var columns = res.getColumns(); var record = res.fetchOne(); while (record) { for (index in columns) { print (columns[index].getColumnName() + ": " + record[index] + "\n"); } // Get the next record record = res.fetchOne(); } } else { // INSERT, UPDATE, DELETE, ... print('Rows affected: ' + res.getAffectedRowCount()); } } var res = mySession.sql('CALL my_proc()').execute(); // Prints each returned result var more = true; while (more) { print_result(res); more = res.nextResult(); }
MySQL Shell Python Code
def print_result(res): if res.has_data(): # SELECT columns = res.get_columns() record = res.fetch_one() while record: index = 0 for column in columns: print("%s: %s \n" % (column.get_column_name(), record[index])) index = index + 1 # Get the next record record = res.fetch_one() else: #INSERT, UPDATE, DELETE, ... print('Rows affected: %s' % res.get_affected_items_count()) res = mySession.sql('CALL my_proc()').execute() # Prints each returned result more = True while more: print_result(res) more = res.next_result()
Node.js JavaScript Code
function print_result(res) { if (res.hasData()) { // SELECT var columns = res.getColumns(); var record = res.fetchOne(); while (record) { for (index in columns) { console.log(columns[index].getColumnName() + ": " + record[index]); } // Get the next record record = res.fetchOne(); } } else { // INSERT, UPDATE, DELETE, ... console.log('Rows affected: ' + res.getAffectedRowsCount()); } } mySession.sql('CALL my_proc()') .execute() .then(function (res) { // Prints each returned result var more = true; while (more) { print_result(res); more = res.nextResult(); } })
C# Code
var res = Session.SQL("CALL my_proc()").Execute(); if (res.HasData) { do { Console.WriteLine("New resultset"); while (res.Next()) { Console.WriteLine(res.Current); } } while (res.NextResult()); }
Python Code
# Connector/Python def print_result(res): if res.has_data(): # SELECT columns = res.get_columns() record = res.fetch_one() while record: index = 0 for column in columns: print("%s: %s \n" % (column.get_column_name(), record[index])) index = index + 1 # Get the next record record = res.fetch_one() else: #INSERT, UPDATE, DELETE, ... print('Rows affected: %s' % res.get_affected_row_count()) res = mySession.sql('CALL my_proc()').execute() # Prints each returned result more = True while more: print_result(res) more = res.next_result()
Java Code
SqlResult res = mySession.sql("CALL my_proc()").execute();
C++ Code
SqlResult res = mysession.sql("CALL my_proc()").execute(); while (true) { if (res.hasData()) { cout << "List of rows in the resultset." << endl; for (Row row; (row = res.fetchOne());) { cout << "next row: "; for (unsigned i = 0; i < row.colCount(); ++i) cout << row[i] << ", "; cout << endl; } } else { cout << "No rows in the resultset." << endl; } if (!res.nextResult()) break; cout << "Next resultset." << endl; }
При применении Node.js отдельные строки могут быть немедленно
возвращены, используя отзыв, который должен быть предоставлен методом
execute()
. Чтобы определить отдельные наборы
результатов, можно обеспечить второй отзыв, который вызывают для метаданных,
которые отмечают начало набора результатов.
Node.js JavaScript Code
var resultcount = 0; var res = session .sql('CALL my_proc()') .execute( function (row) { console.log(row); }, function (meta) { console.log('Begin of result set number ', resultCount++); } );
Количество наборов результатов не известно немедленно после выполнения запроса. Результаты запроса могут подаваться клиенту или буферизоваться в клиенте. При этом клиент не может сказать, вернет ли запрос больше, чем один набор результатов.
Результаты содержат метаданные, связанные с происхождением и типами
результатов запросов. Эти метаданные могут использоваться запросами, которые
должны иметь дело с динамическими результатами запроса или форматированием
результата для преобразования или показа. Метаданные результата доступны
через экземпляры Column
. Множество столбцов
может быть получено из любого RowResult, используя
метод getColumns()
.
Например, следующие метаданные возвращены в ответ на запрос
SELECT 1+1 AS a, b
FROM mydb.some_table_with_b AS b_table
.
Column[0].databaseName = NULL Column[0].tableName = NULL Column[0].tableLabel = NULL Column[0].columnName = NULL Column[0].columnLabel = "a" Column[0].type = BIGINT Column[0].length = 3 Column[0].fractionalDigits = 0 Column[0].numberSigned = TRUE Column[0].collationName = "binary" Column[0].characterSetName = "binary" Column[0].padded = FALSE Column[1].databaseName = "mydb" Column[1].tableName = "some_table_with_b" Column[1].tableLabel = "b_table" Column[1].columnName = "b" Column[1].columnLabel = "b" Column[1].type = STRING Column[1].length = 20 (e.g.) Column[1].fractionalDigits = 0 Column[1].numberSigned = TRUE Column[1].collationName = "utf8mb4_general_ci" Column[1].characterSetName = "utf8mb4" Column[1].padded = FALSE
Все реализации DevAPI показывают методы, показанные в диаграмме UML в
начале этой главы. Все реализации позволяют итеративное использование набора
результатов через fetchOne()
,
fetchAll()
и
nextResult()
.
В дополнение к объединенному API драйверы должны осуществить языковые
итеративные образцы. Это относится к любому типу набора данных
(DocResult, RowResult, SqlResult) и к списку элементов, возвращенных
fetchAll()
. Можно выбрать, хотите ли вы, чтобы
код вашего приложения X DevAPI предложил тот же самый стиль на всех
используемых языках программирования или выбрал естественный
стиль языка программирования.