Обновление поля в SQLite (Flutter) - PullRequest
2 голосов
/ 27 мая 2020

Давайте воспользуемся этим фрагментом кода в качестве примера. Модель данных очень проста:

class Dog {
  final int id;
  final String name;
  final int age;

  Dog({this.id, this.name, this.age});
}

Для обновления информации я использую эту функцию:

Future<void> updateDog(Dog dog) async {
  // Get a reference to the database.
  final db = await database;

  // Update the given Dog.
  await db.update(
    'dogs',
    dog.toMap(),
    // Ensure that the Dog has a matching id.
    where: "id = ?",
    // Pass the Dog's id as a whereArg to prevent SQL injection.
    whereArgs: [dog.id],
  );
}

await updateDog(Dog(id: 0, name: 'Fido', age: 42));

Она отлично работает и никаких проблем не возникает. Теперь вопрос, как обновить только поле возраст без использования name ? Итак, в основном я хочу сделать что-то вроде этого

await updateDog(Dog(id: 0, age: 35));

и ожидать в результате «имя: Fi go, возраст: 35». Но вместо этого он удаляет Fido из null . В результате я получаю следующее: «name: null, age: 35».

Ответы [ 2 ]

1 голос
/ 28 мая 2020

Пример в документации выглядит так:

// Update Fido's age and save it to the database.
  fido = Dog(
    id: fido.id,
    name: fido.name,
    age: fido.age + 7,
  );
  await updateDog(fido);

Вы либо подходите к нему с помощью необработанного запроса SQL, как в ответе chunhunghan, либо запрашиваете Dog с идентификатором, а затем переопределяете поля, затем обновите.

Почему?

Давайте посмотрим на ваш код обновления:

await updateDog(Dog(id: 0, age: 35));

Когда вызывается строка обновления, Dog.toMap() будет будет вызван, и это будет выглядеть так, как будто вы обновляете имя до null.

Чтобы вы могли делать то, что хотите, вот код:

 Future<Dog> getDog(int id) async {
    List<Map> result = await database.query(..... whereArgs: [id]);
    if (result.length > 0) {
      return new Dog.fromMap(result.first);
    }
    return null;
 }

// Now in code
fido = await getDog(id);
// Update Fido's age and save it to the database.
fido = Dog(
 id: fido.id,
 name: fido.name,
 age: 35, //<--
);
await updateDog(fido);

0 голосов
/ 28 мая 2020

Вы можете скопировать и вставить полный код ниже
В примере кода есть две записи для демонстрации эффекта обновления
Решение 1. Вы можете использовать rawUpdate
фрагмент кода

int count = await db.rawUpdate('UPDATE dogs SET age = ? WHERE id = ?', [35, 0]);

Решение 2: Вы можете изменить toMap, чтобы вернуть только id и age

Future<void> updateDog1(Dog dog) async {
    // Get a reference to the database.
    final db = await database;

    // Update the given Dog.
    await db.update(
      'dogs',
      dog.toMap1(),
 ...
Map<String, dynamic> toMap1() {
    return {
      'id': id,
      'age': age,
    };
  }

fido = Dog(
    id: fido.id,
    name: "not care",
    age: 35,
  );
 await updateDog1(fido);

вывод

I/flutter ( 6570): [Dog{id: 0, name: Fido, age: 42}, Dog{id: 1, name: abc, age: 10}]
I/flutter ( 6570): updated: 1
I/flutter ( 6570): [Dog{id: 0, name: Fido, age: 35}, Dog{id: 1, name: abc, age: 10}]

решение полного кода 1

import 'dart:async';

import 'package:flutter/widgets.dart';

import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';

void main() async {
  // Avoid errors caused by flutter upgrade.
  // Importing 'package:flutter/widgets.dart' is required.
  WidgetsFlutterBinding.ensureInitialized();
  final database = openDatabase(
    // Set the path to the database. Note: Using the `join` function from the
    // `path` package is best practice to ensure the path is correctly
    // constructed for each platform.
    join(await getDatabasesPath(), 'doggie_database.db'),
    // When the database is first created, create a table to store dogs.
    onCreate: (db, version) {
      return db.execute(
        "CREATE TABLE dogs(id INTEGER PRIMARY KEY, name TEXT, age INTEGER)",
      );
    },
    // Set the version. This executes the onCreate function and provides a
    // path to perform database upgrades and downgrades.
    version: 1,
  );

  Future<void> insertDog(Dog dog) async {
    // Get a reference to the database.
    final Database db = await database;

    // Insert the Dog into the correct table. Also specify the
    // `conflictAlgorithm`. In this case, if the same dog is inserted
    // multiple times, it replaces the previous data.
    await db.insert(
      'dogs',
      dog.toMap(),
      conflictAlgorithm: ConflictAlgorithm.replace,
    );
  }

  Future<List<Dog>> dogs() async {
    // Get a reference to the database.
    final Database db = await database;

    // Query the table for all The Dogs.
    final List<Map<String, dynamic>> maps = await db.query('dogs');

    // Convert the List<Map<String, dynamic> into a List<Dog>.
    return List.generate(maps.length, (i) {
      return Dog(
        id: maps[i]['id'],
        name: maps[i]['name'],
        age: maps[i]['age'],
      );
    });
  }

  Future<void> updateDog(Dog dog) async {
    // Get a reference to the database.
    final db = await database;

    // Update the given Dog.
    await db.update(
      'dogs',
      dog.toMap(),
      // Ensure that the Dog has a matching id.
      where: "id = ?",
      // Pass the Dog's id as a whereArg to prevent SQL injection.
      whereArgs: [dog.id],
    );
  }

  Future<void> deleteDog(int id) async {
    // Get a reference to the database.
    final db = await database;

    // Remove the Dog from the database.
    await db.delete(
      'dogs',
      // Use a `where` clause to delete a specific dog.
      where: "id = ?",
      // Pass the Dog's id as a whereArg to prevent SQL injection.
      whereArgs: [id],
    );
  }

  var fido = Dog(
    id: 0,
    name: 'Fido',
    age: 42,
  );

  var fido1 = Dog(
    id: 1,
    name: 'abc',
    age: 10,
  );

  // Insert a dog into the database.
  await insertDog(fido);
  await insertDog(fido1);

  // Print the list of dogs (only Fido for now).
  print(await dogs());
/*
  // Update Fido's age and save it to the database.
  fido = Dog(
    id: fido.id,
    name: fido.name,
    age: fido.age + 7,
  );
  await updateDog(fido);

  // Print Fido's updated information.
  print(await dogs());*/

  final Database db = await database;
  int count =
      await db.rawUpdate('UPDATE dogs SET age = ? WHERE id = ?', [35, 0]);
  print('updated: $count');
  print(await dogs());

  /*// Delete Fido from the database.
  await deleteDog(fido.id);

  // Print the list of dogs (empty).
  print(await dogs());*/
}

class Dog {
  final int id;
  final String name;
  final int age;

  Dog({this.id, this.name, this.age});

  Map<String, dynamic> toMap() {
    return {
      'id': id,
      'name': name,
      'age': age,
    };
  }

  // Implement toString to make it easier to see information about
  // each dog when using the print statement.
  @override
  String toString() {
    return 'Dog{id: $id, name: $name, age: $age}';
  }
}

полное решение кода 2

import 'dart:async';

import 'package:flutter/widgets.dart';

import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';

void main() async {
  // Avoid errors caused by flutter upgrade.
  // Importing 'package:flutter/widgets.dart' is required.
  WidgetsFlutterBinding.ensureInitialized();
  final database = openDatabase(
    // Set the path to the database. Note: Using the `join` function from the
    // `path` package is best practice to ensure the path is correctly
    // constructed for each platform.
    join(await getDatabasesPath(), 'doggie_database.db'),
    // When the database is first created, create a table to store dogs.
    onCreate: (db, version) {
      return db.execute(
        "CREATE TABLE dogs(id INTEGER PRIMARY KEY, name TEXT, age INTEGER)",
      );
    },
    // Set the version. This executes the onCreate function and provides a
    // path to perform database upgrades and downgrades.
    version: 1,
  );

  Future<void> insertDog(Dog dog) async {
    // Get a reference to the database.
    final Database db = await database;

    // Insert the Dog into the correct table. Also specify the
    // `conflictAlgorithm`. In this case, if the same dog is inserted
    // multiple times, it replaces the previous data.
    await db.insert(
      'dogs',
      dog.toMap(),
      conflictAlgorithm: ConflictAlgorithm.replace,
    );
  }

  Future<List<Dog>> dogs() async {
    // Get a reference to the database.
    final Database db = await database;

    // Query the table for all The Dogs.
    final List<Map<String, dynamic>> maps = await db.query('dogs');

    // Convert the List<Map<String, dynamic> into a List<Dog>.
    return List.generate(maps.length, (i) {
      return Dog(
        id: maps[i]['id'],
        name: maps[i]['name'],
        age: maps[i]['age'],
      );
    });
  }

  Future<void> updateDog(Dog dog) async {
    // Get a reference to the database.
    final db = await database;

    // Update the given Dog.
    await db.update(
      'dogs',
      dog.toMap(),
      // Ensure that the Dog has a matching id.
      where: "id = ?",
      // Pass the Dog's id as a whereArg to prevent SQL injection.
      whereArgs: [dog.id],
    );
  }

  Future<void> updateDog1(Dog dog) async {
    // Get a reference to the database.
    final db = await database;

    // Update the given Dog.
    await db.update(
      'dogs',
      dog.toMap1(),
      // Ensure that the Dog has a matching id.
      where: "id = ?",
      // Pass the Dog's id as a whereArg to prevent SQL injection.
      whereArgs: [dog.id],
    );
  }

  Future<void> deleteDog(int id) async {
    // Get a reference to the database.
    final db = await database;

    // Remove the Dog from the database.
    await db.delete(
      'dogs',
      // Use a `where` clause to delete a specific dog.
      where: "id = ?",
      // Pass the Dog's id as a whereArg to prevent SQL injection.
      whereArgs: [id],
    );
  }

  var fido = Dog(
    id: 0,
    name: 'Fido',
    age: 42,
  );

  var fido1 = Dog(
    id: 1,
    name: 'abc',
    age: 10,
  );

  // Insert a dog into the database.
  await insertDog(fido);
  await insertDog(fido1);

  // Print the list of dogs (only Fido for now).
  print(await dogs());

  // Update Fido's age and save it to the database.
  fido = Dog(
    id: fido.id,
    name: "not care",
    age: 35,
  );
  await updateDog1(fido);

  // Print Fido's updated information.
  print(await dogs());

  /*final Database db = await database;
  int count =
      await db.rawUpdate('UPDATE dogs SET age = ? WHERE id = ?', [35, 0]);
  print('updated: $count');
  print(await dogs());*/

  /*// Delete Fido from the database.
  await deleteDog(fido.id);

  // Print the list of dogs (empty).
  print(await dogs());*/
}

class Dog {
  final int id;
  final String name;
  final int age;

  Dog({this.id, this.name, this.age});

  Map<String, dynamic> toMap() {
    return {
      'id': id,
      'name': name,
      'age': age,
    };
  }

  Map<String, dynamic> toMap1() {
    return {
      'id': id,
      'age': age,
    };
  }

  // Implement toString to make it easier to see information about
  // each dog when using the print statement.
  @override
  String toString() {
    return 'Dog{id: $id, name: $name, age: $age}';
  }
}
...