RussianLDP Рейтинг@Mail.ru
WebMoney: 
WMZ Z294115950220 
WMR R409981405661 
WME E134003968233 
Visa 
4274 3200 2453 6495 

Глава 9. Работа с наборами результатов

Этот раздел объясняет, как работать с результатами обработки.

9.1. Классы набора результатов

Все операции по базе данных возвращают результат. Тип возвращенного результата зависит от операции, которая была выполнена. Различные типы возвращенных результатов обрисованы в общих чертах в следующей таблице.

Класс результата

Возвращен

Обеспечивает

Result

add().execute(), insert().execute(), ...

affectedRows, lastInsertId, предупреждения

SqlResult

session.sql()

affectedRows, lastInsertId, предупреждения, принесенный набор данных

DocResult

find().execute()

Принесенный набор данных

RowResult

select.execute()

Принесенный набор данных

Следующая диаграмма классов дает основной обзор обработки результата.

Рис. 9.1. Диаграмма классов


9.2. Работа со значениями 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, но не ограничиваются ими.

9.3. Работа с наборами данных

Операции, которые приносят элементы данных, возвращают набор данных в противоположность операциям, которые изменяют данные и возвращают набор результатов. Элементы данных могут быть прочитаны из базы данных через 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;
}

9.4. Установка всех элементов данных сразу

В дополнение к образцу использования 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() не может вернуть управление прежде, чем закончит чтение результатов с сервера.

9.5. Работа с наборами результатов SQL

Когда вы выполняете операцию 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++);
  }
);

Количество наборов результатов не известно немедленно после выполнения запроса. Результаты запроса могут подаваться клиенту или буферизоваться в клиенте. При этом клиент не может сказать, вернет ли запрос больше, чем один набор результатов.

9.6. Работа с метаданными

Результаты содержат метаданные, связанные с происхождением и типами результатов запросов. Эти метаданные могут использоваться запросами, которые должны иметь дело с динамическими результатами запроса или форматированием результата для преобразования или показа. Метаданные результата доступны через экземпляры 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

9.7. Поддержка языковых итераторов

Все реализации DevAPI показывают методы, показанные в диаграмме UML в начале этой главы. Все реализации позволяют итеративное использование набора результатов через fetchOne(), fetchAll() и nextResult(). В дополнение к объединенному API драйверы должны осуществить языковые итеративные образцы. Это относится к любому типу набора данных (DocResult, RowResult, SqlResult) и к списку элементов, возвращенных fetchAll(). Можно выбрать, хотите ли вы, чтобы код вашего приложения X DevAPI предложил тот же самый стиль на всех используемых языках программирования или выбрал естественный стиль языка программирования.

Поиск

 

Найди своих коллег!

Вы можете направить письмо администратору этой странички, Алексею Паутову. mailto:alexey.v.pautov@mail.ru