Currently using SQlite, practicing how to save text from textfield. I can do it with only 1 textfield, but when make it even as low as 1 more textfield, it fails me.
Exception has occurred. SqfliteDatabaseException (DatabaseException(table claims has no column named number (code 1 SQLITE_ERROR): , while compiling: INSERT INTO claims (id, name, number) VALUES (NULL, ?, ?)) sql 'INSERT INTO claims (id, name, number) VALUES (NULL, ?, ?)' args [tt, 605])
// ignore_for_file: prefer_const_constructors
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
// https://www.youtube.com/watch?v=noi6aYsP7Go
// this is where im getting all these from
main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(SqliteApp());
}
class SqliteApp extends StatefulWidget {
const SqliteApp({Key? key}) : super(key: key);
@override
_SqliteAppState createState() => _SqliteAppState();
}
class _SqliteAppState extends State<SqliteApp> {
int? selectedId;
final textController = TextEditingController();
final textController2 = TextEditingController();
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('TEST TEST')),
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Center(
child: Column(
children: [
TextField(
controller: textController,
),
TextField(
controller: textController2,
keyboardType: TextInputType.number,
),
SizedBox(
height: 500,
child: FutureBuilder<List<Claim>>(
future: DatabaseHelper.instance.getClaim(),
builder: (BuildContext context,
AsyncSnapshot<List<Claim>> snapshot) {
if (!snapshot.hasData) {
return Center(
child: Text('Loading...'),
);
}
return snapshot.data!.isEmpty
? Center(
child: Text('No Claims in List.'),
)
: ListView(
children: snapshot.data!.map((claim) {
return Center(
child: Card(
color: selectedId == claim.id
? Colors.grey
: Colors.white,
child: ListTile(
title: Text(claim.name),
onTap: () {
setState(() {
if (selectedId == null) {
textController.text = claim.name;
textController2.text =
claim.number;
selectedId = claim.id;
} else {
textController.text = '';
textController2.text = '';
selectedId = null;
}
});
},
onLongPress: () {
setState(() {
DatabaseHelper.instance
.remove(claim.id!);
});
},
),
),
);
}).toList(),
);
},
),
),
],
),
),
),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.save),
onPressed: () async {
if (textController.text.isEmpty) {
null;
} else {
selectedId != null
? await DatabaseHelper.instance.update(
Claim(
id: selectedId,
name: textController.text,
number: textController2.text),
)
: await DatabaseHelper.instance.add(
Claim(
name: textController.text,
number: textController2.text),
);
setState(() {
textController.clear();
textController2.clear();
});
}
},
),
),
);
}
}
class Claim {
final int? id;
final String name;
final String number;
Claim({this.id, required this.name, required this.number});
factory Claim.fromMap(Map<String, dynamic> json) =>
new Claim(id: json['id'], name: json['name'], number: json['number']);
Map<String, dynamic> toMap() {
return {
'id': id,
'name': name,
'number': number,
};
}
}
class DatabaseHelper {
DatabaseHelper._privateConstructor();
static final DatabaseHelper instance = DatabaseHelper._privateConstructor();
static Database?
_database; // if the variable doesnt exist,,,,,,,, this (under) will initalise the database, and use set variable
Future<Database> get database async => _database ??= await _initDatabase();
Future<Database> _initDatabase() async {
Directory documentsDirectory = await getApplicationDocumentsDirectory();
String path = join(documentsDirectory.path, 'claims.db');
return await openDatabase(
path,
version: 2,
onCreate: _onCreate,
);
}
Future _onCreate(Database db, int version) async {
await db.execute('''
CREATE TABLE claims(
id INTEGER PRIMARY KEY,
name TEXT
number TEXT
)
''');
}
Future<List<Claim>> getClaim() async {
Database db = await instance.database;
var claims = await db.query('claims', orderBy: 'id');
List<Claim> claimList =
claims.isNotEmpty ? claims.map((c) => Claim.fromMap(c)).toList() : [];
return claimList;
}
Future<int> add(Claim claim) async {
Database db = await instance.database;
return await db.insert('claims', claim.toMap());
}
Future<int> remove(int id) async {
Database db = await instance.database;
return await db.delete('claims', where: 'id = ?', whereArgs: [id]);
}
Future<int> update(Claim claim) async {
Database db = await instance.database;
return await db.update('claims', claim.toMap(),
where: 'id = ?', whereArgs: [claim.id]);
}
}
With this code, I keep getting the code 1 SQLITE_ERROR, i tried tweaking it over and over again but alas, can't find the solution. Still quite an amateur in flutter so I don't have much experience
CodePudding user response:
I think you missed a comma when creating the Claim table
Future _onCreate(Database db, int version) async {
await db.execute('''
CREATE TABLE claims(
id INTEGER PRIMARY KEY,
name TEXT,
number TEXT
)
''');
}
I would like to propose a better way for readability
db.execute(
"CREATE TABLE claims("
"id INTEGER PRIMARY KEY, "
"name TEXT, "
"number TEXT)"
);
CodePudding user response:
The name of the database table is not comma (,) after the TEXT of the column, name TEXT,
Change the version : 1, uninstall the app from your physical device and reinstall.
Hopefully the problem will be solved.
Future _onCreate(Database db, int version) async {
await db.execute('''
CREATE TABLE claims(
id INTEGER PRIMARY KEY,
name TEXT, //You didn't give a comma here
number TEXT
)
''');
}