I have a issue where when I enter the first record into my data it goes into slot ID = 1. But if i enter another record it doesnt increment to id = 2 and tries to use ID = 1 even though i stated AUTOINCREMENT in the SQL code.
SQLite class
class SQLiteHelper(context: Context):SQLiteOpenHelper(context, DATABASE_NAME,null, DATABASE_VERSION){
companion object{
private const val DATABASE_VERSION = 1
private const val DATABASE_NAME = "anki.db"
private const val TBL_WORD = "tbl_word"
private const val ID = "id"
private const val DATE = "date"
private const val ENGLISHWORD = "englishWord"
private const val JAPANESEWORD = "jpnWord"
private const val TIME = "time"
private const val ANSWER = "answer"
}
override fun onCreate(db: SQLiteDatabase?) {
val createTblWord = ("CREATE TABLE "+ TBL_WORD + "("
+ ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"+ DATE + " TEXT,"+ ENGLISHWORD + " TEXT,"
+ JAPANESEWORD + " TEXT,"+ TIME + " INTEGER,"+ ANSWER + " INTEGER"+")")
db?.execSQL(createTblWord)
}
override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {
db!!.execSQL("DROP TABLE IF EXISTS $TBL_WORD")
onCreate(db)
}
fun insertWord(word: WordModel): Long{
val db = this.writableDatabase
val contentValues = ContentValues()
contentValues.put(ID,word.id)
contentValues.put(DATE,word.date)
contentValues.put(ENGLISHWORD,word.engword)
contentValues.put(JAPANESEWORD,word.jpword)
contentValues.put(TIME,word.time)
contentValues.put(ANSWER,word.answer)
val success = db.insert(TBL_WORD, null , contentValues)
db.close()
return success
}
Main class add word method
private fun addWord(){
val date = etDate.text.toString()
val jpword = etJpWord.text.toString()
val engword = etEngWord.text.toString()
if(date.isEmpty() || jpword.isEmpty() || engword.isEmpty()){//必要な情報が入力してない場合
Toast.makeText(this,"必要な情報を入力してください。",Toast.LENGTH_SHORT).show()
clearEditText()
}else{
val word = WordModel(date=date, jpword = jpword, engword = engword)
val status = sqliteHelper.insertWord(word)
//Check Insert success or not success
if(status > -2){
Toast.makeText(this,"単語を追加しました",Toast.LENGTH_SHORT).show()
}else{
Toast.makeText(this,"データが保存されてないようです。",Toast.LENGTH_SHORT).show()
}
}
}
Shouldnt ID auto increment ?? Tried debug and Id clearly doesnt auto increment and tries to use the same id
Can you please share your WordModel? What do you use for id when create a new word in your addWord() method:
val word = WordModel(date=date, jpword = jpword, engword = engword)
Perhaps you use default id value of your WordModel like here: data class WordModel(id: Long? = 1, ...). And if it's true you can change the default value of id here to be like data class WordModel(id: Long? = null, ...) and it should work to insert auto-generated id values for db rows.
In another case you can use base SQLite BaseColumns._ID for creating your table like
"CREATE TABLE $TBL_WORD (${BaseColumns._ID} INTEGER PRIMARY KEY AUTOINCREMENT, $ENGLISHWORD TEXT, $JAPANESEWORD TEXT, etc)"
and then just don't put id like a value at all in your SQLiteHelper::insertWord(word: WordModel) method. It will be automatically generated like an auto incremented value for any new row in db.
You can see example in docs.
//try to change key_id query like this
public void onCreate(SQLiteDatabase db) {
String CREATE_CONTACTS_TABLE = "CREATE TABLE " + TABLE_CONTACTS + "("
+ KEY_ID + " INTEGER PRIMARY KEY," + KEY_NAME + " TEXT,"
+ KEY_PH_NO + " TEXT" + ")";
db.execSQL(CREATE_CONTACTS_TABLE);
}
Related
Suposse that i have an android studio App where i can add companies, and inside those companies i can also add employees. Now, i'm trying to get the employees list showing only the elements of the company I selected before (In an unique activity for showing employees).
I created two classes:
data class Company(val id:Int, val name:String, val telephone:String)
data class Employee (val id:Int, val name:String, val telephone:String, val idCompany:Int)
And in my SQLiteHelper I created the tables for each one, with a foreign key in Employees to make a relation
private val TABLE_COMPANY = "CompanyTable"
private val TABLE_EMPLOYEE = "EmployeeTable"
//Company table
private val COMPANY_ID = "_id"
private val COMPANY_NAME = "name"
private val COMPANY_TL = "telephone"
//Employee table
private val EMPLOYEE_ID = "id"
private val EMPLOYEE_NAME = "name"
private val EMPLOYEE_TL = "telephone"
private val EMPLOYEE_COMPANY_ID = "id"
}
override fun onCreate(db: SQLiteDatabase?) {
val CREATE_COMPANY_TABLE = ("CREATE TABLE " + TABLE_COMPANY + "("
+ COMPANY_ID + " INTEGER PRIMARY KEY,"
+ COMPANY_NAME + " TEXT,"
+ COMPANY_TL + " TEXT" + ")")
val CREATE_EMPLOYEE_TABLE = ("CREATE TABLE " + TABLE_EMPLOYEE + "("
+ EMPLOYEE_ID + " INTEGER PRIMARY KEY,"
+ EMPLOYEE_NAME + " TEXT,"
+ EMPLOYEE_TL + " INTEGER,"
+ EMPLOYEE_COMPANY_ID + " INTEGER,"
+ " FOREIGN KEY ("+ EMPLOYEE_COMPANY_ID+") REFERENCES "+TABLE_COMPANY+"("+ COMPANY_ID+"))")
db?.execSQL(CREATE_EMPLOYEE_TABLE)
db?.execSQL(CREATE_COMPANY_TABLE)
}
So, I made two activities with recyclerviews, one for the Companies and the other for the employees.
When i click a company, the employees activity opens and it shows a list of them.
But it shows all the employees i have, so i'm trying to figure out how to show only the ones that i saved with the same id of the Company that i clicked in the previous activity.
But i don't know how to proceed now
Here is the DAO function that shows the employees:
fun viewEmployee(): ArrayList<Employee> {
val empList: ArrayList<Employee> = ArrayList<Employee>()
// Query to select the records
val selectQuery = "SELECT L.$EMPLOYEE_NAME, L.$EMPLOYEE_TL, L.$EMPLOYEE_ID, L.$EMPLOYEE_COMPANY_ID, C.$COMPANY_ID" +
"FROM $TABLE_EMPLOYEE as L, $TABLE_COMPANY as C" +
"WHERE L.$EMPLOYEE_COMPANY_ID = C.$COMPANY_ID"
val db = this.readableDatabase
var cursor: Cursor? = null
try {
cursor = db.rawQuery(selectQuery, null)
} catch (e: SQLiteException) {
db.execSQL(selectQuery)
return ArrayList()
}
var id: Int
var name: String
var telephone: String
var idCompany: Int
if (cursor.moveToFirst()) {
do {
id = cursor.getInt(cursor.getColumnIndex(EMPLOYEE_ID))
name = cursor.getString(cursor.getColumnIndex(EMPLOYEE_NAME))
telephone = cursor.getString(cursor.getColumnIndex(EMPLOYEE_TL))
idCompany = cursor.getInt(cursor.getColumnIndex(EMPLOYEE_COMPANY_ID))
val employee = Employee(id = id, name = name, telephone = telephone, idCompany = idCompany)
empList.add(employee)
} while (cursor.moveToNext())
}
return empList
}
And here is the activity that shows the employees
class ManagerEmp : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_manager_emp)
setList()
createEmp.setOnClickListener{
val intent = Intent(this, CreateEmp::class.java)
startActivity(intent)
}
}
/**
* Gets DB employee list
*/
private fun getItemsList(): ArrayList<Employee> {
//creating the instance of DatabaseHandler class
val databaseHandler = DataBaseHelper(this)
//calling the viewEmployee method of DatabaseHandler class to read the records
val empList: ArrayList<Employee> = databaseHandler.viewEmployee()
return empList
}
/**
* Generates the list
*/
private fun setList() {
recyclerEmp.layoutManager = LinearLayoutManager(this)
val itemAdapter = empAdapter(this, getItemsList())
recyclerEmp.adapter = itemAdapter
}
}
It sounds simple but it isn't (At least for me)
I thought of getting the id value of the company and pass it to the employee list activity, so i can use to compare it, but idk how, i'm pretty new in kotlin (And programming in general)
If you can give an answer, you would be saving my life.
H E L P
First you have to obtain companyId you want to filter by. It can be done for example by adding onClickListener in RecyclerView.
Then you will need additional query which will be used for filtering by companyId.
For example if companyId is stored in filteredCompanyId variable you can add additional filter condition (WHERE ... AND C.$COMPANY_ID == $filteredCompanyId):
val filteredCompanyId = 5
val query = """
SELECT L.$EMPLOYEE_NAME,
L.$EMPLOYEE_TL,
L.$EMPLOYEE_ID,
L.$EMPLOYEE_COMPANY_ID,
C.$COMPANY_ID
FROM $TABLE_EMPLOYEE AS L,
$TABLE_COMPANY AS C
WHERE L.$EMPLOYEE_COMPANY_ID = C.$COMPANY_ID
AND C.$COMPANY_ID == $filteredCompanyId
"""
I'm in kotlin and try to create some app. I created SQLite database for android app. In DB i have "login" and "password". How I can read it for login?
My Database.kt
fun insertIntoPartner(plogin: String?, ppassword: String?): Boolean {
var contentValues = ContentValues()
contentValues.put("plogin", plogin)
contentValues.put("ppassword", ppassword)
val rowId = writableDatabase.insert(PARTNER, null, contentValues)
return rowId>0
}
My login code:
bin.setOnClickListener {
if (login.text.toString() == // here i read database login
&& password.text.toString() == here i read database password) {
val i = Intent(this, NavigationMenu::class.java)
startActivity(i)
} else toast("No login or password")
Thank for all suggestions.
UPD 1:
fun checkUser(plogin: String?, ppassword: String?): Boolean {
val columns = arrayOf(pid)
val db = this.readableDatabase
val selection = "$plogin = ? AND $ppassword = ?"
val selectionArgs = arrayOf(plogin, ppassword)
val cursor = db.query(PARTNER, columns, selection, selectionArgs,
null, null, null)
val cursorCount = cursor.count
cursor.close()
db.close()
if (cursorCount > 0) return true
else return false
}
How I understood I must replace "USER_ID", "TABLE_NAME" and etc. to my fields. But what if I have for id "pid (INTEGER PRIMARY KEY)"? When I wrote "pid" it's red and tell "unresolved reference". What is my mistake?
My CREATE_TABLE looks like:
companion object {
val PARTNER = "partner"
val DB_VERSION = 1
val CREATE_TABLE_PARTNER = "CREATE TABLE partner(pid INTEGER PRIMARY KEY, plogin TEXT, ppassword TEXT," +
" pname TEXT, psale TEXT, pasale TEXT, pengsale TEXT, prusdescription TEXT, pengdescription TEXT," +
" pinn TEXT, pemail TEXT, pphonenumber TEXT, psitecompany TEXT, pstreet TEXT, pcity TEXT," +
" pregion TEXT, pcountry TEXT, pindex TEXT)"
val SELECT_PARTNER = "SELECT * from partner"
}
In your MyDatabase.kt class :
/**
* This method to check user exist or not
*
* #param email
* #param password
* #return true/false
*/
fun checkUser(email: String, password: String): Boolean {
// array of columns to fetch
val columns = arrayOf(COLUMN_USER_ID)
val db = this.readableDatabase
// selection criteria
val selection = "$COLUMN_USER_EMAIL = ? AND $COLUMN_USER_PASSWORD = ?"
// selection arguments
val selectionArgs = arrayOf(email, password)
// query user table with conditions
/**
* Here query function is used to fetch records from user table this function works like we use sql query.
* SQL query equivalent to this query function is
* SELECT user_id FROM user WHERE user_email = 'viral#exmaple.com' AND user_password = 'qwerty';
*/
val cursor = db.query(TABLE_USER, //Table to query
columns, //columns to return
selection, //columns for the WHERE clause
selectionArgs, //The values for the WHERE clause
null, //group the rows
null, //filter by row groups
null) //The sort order
val cursorCount = cursor.count
cursor.close()
db.close()
if (cursorCount > 0)
return true
return false
}
Then MyLogin.kt class :
private fun verifyFromSQLite() {
// Make changes as per your requirement
if (MyDatabase!!.checkUser(textInputEditTextEmail!!.text.toString().trim { it <= ' ' }, textInputEditTextPassword!!.text.toString().trim { it <= ' ' })) {
val accountsIntent = Intent(activity, UserActivity::class.java)
emptyInputEditText()
startActivity(accountsIntent)
} else {
// Snack Bar to show success message that record is wrong
Snackbar.make(nestedScrollView!!, getString(R.string.error_email_password), Snackbar.LENGTH_LONG).show()
}
}
Edited: see the create table look like:
// create table sql query
private val CREATE_USER_TABLE = ("CREATE TABLE " + TABLE_USER + "("
+ COLUMN_USER_ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + COLUMN_USER_NAME + " TEXT,"
+ COLUMN_USER_EMAIL + " TEXT," + COLUMN_USER_PASSWORD + " TEXT" + ")")
I'm fairly new to Android, Kotlin, and SQLLite.
I have this table creation.
val create = "CREATE TABLE IF NOT EXISTS $TABLE_NAME (" +
"$COLUMN_ID INTEGER PRIMARY KEY AUTOINCREMENT, " +
"$COLUMN_USERNAME STRING, $COLUMN_PASSWORD STRING, $COLUMN_EMAIL STRING, $COLUMN_LAST_LOGIN DATETIME NULL, " +
"$COLUMN_PRIV_ACCESS_ADMIN_LIST BOOLEAN, $COLUMN_PRIV_CHANGE_ADMIN_LIST BOOLEAN, $COLUMN_PRIV_SEND_EMAIL_REPORT BOOLEAN, " +
"$COLUMN_IS_ACTIVE BOOLEAN" +
")"
db.execSQL(create)
I can successfully add new data with this:
val values = ContentValues()
values.put(COLUMN_USERNAME, "admin")
values.put(COLUMN_PASSWORD, "password")
values.put(COLUMN_EMAIL, "test#test.com")
values.put(COLUMN_PRIV_ACCESS_ADMIN_LIST, true)
values.put(COLUMN_PRIV_CHANGE_ADMIN_LIST, true)
values.put(COLUMN_PRIV_SEND_EMAIL_REPORT, true)
values.put(COLUMN_IS_ACTIVE, admin.isActive)
val db = this.writableDatabase
db.insert(TABLE_NAME, null, values)
I also can successfully retrieve data with this:
val db = this.readableDatabase
val cursor = db.rawQuery("SELECT * FROM $TABLE_NAME", null)
by which I get the info that the data I put there has the ID = 1
But I cannot change the data into something else, either with this code:
val values = ContentValues()
values.put(COLUMN_USERNAME, "adminssss")
values.put(COLUMN_PASSWORD, "passwordsss")
values.put(COLUMN_EMAIL, "test#test.org")
values.put(COLUMN_PRIV_ACCESS_ADMIN_LIST, false)
values.put(COLUMN_PRIV_CHANGE_ADMIN_LIST, true)
values.put(COLUMN_PRIV_SEND_EMAIL_REPORT, false)
values.put(COLUMN_IS_ACTIVE, true)
val db = this.writableDatabase
db.update(TABLE_NAME, values, "$COLUMN_ID=1", arrayOf())
// or
db.update(TABLE_NAME, values, "$COLUMN_ID=?", arrayOf("1"))
Or
val db = this.writableDatabase
val query = "UPDATE $TABLE_NAME " +
"SET $COLUMN_USERNAME = 'adminssss', $COLUMN_PASSWORD = 'passwordsss', $COLUMN_EMAIL = 'test#test.org', " +
"$COLUMN_PRIV_ACCESS_ADMIN_LIST = 0, " +
"$COLUMN_PRIV_CHANGE_ADMIN_LIST = 1, " +
"$COLUMN_PRIV_SEND_EMAIL_REPORT = 0, " +
"$COLUMN_IS_ACTIVE = 1 " +
"WHERE $COLUMN_ID = 1"
db.rawQuery(query, null)
// or
db.execQuery(query)
I'm not too strong with query language, but I've tried to double check the query and can't found anything wrong with it. When the update query is run, which ever version it is from above example, all can run without error, but when I re-select the data again, nothing is changed. The data stays the same like the original first time I put them in.
Can somebody help?
There is nothing wrong with your first update code (both work), it works (see Working example below).
I suspect that you issue might be that you have deleted a row and the added another row. In such a case, because you have AUTOINCREMENT coded such a row would not have an ID as 1 but perhaps two.
You could check the underlying rows by using the logAll function (as used in the Working Example below).
If using the code from the working example then the issues in attempting to use rawQuery and execQuery become moot.
I believe that your issue is how you are viewing the result (or is as previously explained). Consider the following working example :-
Working Example
The Database Helper class, DBHelper.kt (based upon the available code) including the code, such as update as functions :-
class DBHelper(context: Context) : SQLiteOpenHelper(context, DBNAME, null, DBVERSION) {
val all: Cursor
get() = this.writableDatabase.query(TABLE_NAME, null, null, null, null, null, null)
override fun onCreate(db: SQLiteDatabase) {
db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_NAME + "(" +
COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
COLUMN_USERNAME + " STRING, " +
COLUMN_PASSWORD + " STRING, " +
COLUMN_EMAIL + " STRING, " +
COLUMN_LAST_LOGIN + " DATETIME DEFAULT NULL, " +
COLUMN_PRIV_ACCESS_ADMIN_LIST + " BOOLEAN, " +
COLUMN_PRIV_CHANGE_ADMIN_LIST + " BOOLEAN," +
COLUMN_PRIV_SEND_EMAIL_REPORT + " BOOLEAN, " +
COLUMN_IS_ACTIVE + " BOOLEAN" +
")"
)
}
fun add(
username: String,
password: String,
email: String,
privaccessadminlist: Boolean,
privchangeadminlist: Boolean,
privsendemailreport: Boolean,
is_active: Boolean): Long {
val cv = ContentValues()
cv.put(COLUMN_USERNAME, username)
cv.put(COLUMN_PASSWORD, password)
cv.put(COLUMN_EMAIL, email)
cv.put(COLUMN_PRIV_ACCESS_ADMIN_LIST, privaccessadminlist)
cv.put(COLUMN_PRIV_CHANGE_ADMIN_LIST, privchangeadminlist)
cv.put(COLUMN_PRIV_SEND_EMAIL_REPORT, privsendemailreport)
return this.writableDatabase.insert(TABLE_NAME, null, cv)
}
fun logAll() {
val csr = all
var sb = StringBuilder()
while (csr.moveToNext()) {
sb = StringBuilder().append("Row is " + csr.position.toString())
sb.append("\n\tUserName is :").append(csr.getString(csr.getColumnIndex(COLUMN_USERNAME)))
sb.append("\n\tPasword is :").append(csr.getString(csr.getColumnIndex(COLUMN_PASSWORD)))
sb.append("\n\tEmail is :").append(csr.getString(csr.getColumnIndex(COLUMN_EMAIL)))
sb.append("\n\t PRIVACCESSAL is ").append((csr.getInt(csr.getColumnIndex(COLUMN_PRIV_ACCESS_ADMIN_LIST)) > 0).toString())
sb.append("\n\t PRIVCHGAL is ").append((csr.getInt(csr.getColumnIndex(COLUMN_PRIV_CHANGE_ADMIN_LIST)) > 0).toString())
sb.append("\n\t PRIVSNDEMAIL is ").append((csr.getInt(csr.getColumnIndex(COLUMN_PRIV_SEND_EMAIL_REPORT)) > 0).toString())
Log.d("LOGDATA", sb.toString())
}
}
// Suggested update code
fun updateById(id: Long,
username: String,
password: String,
email: String,
privaccessadminlist: Boolean,
privchangeadminlist: Boolean,
privsendemailreport: Boolean,
is_active: Boolean): Int {
val cv = ContentValues()
cv.put(COLUMN_USERNAME, username)
cv.put(COLUMN_PASSWORD, password)
cv.put(COLUMN_EMAIL, email)
cv.put(COLUMN_PRIV_ACCESS_ADMIN_LIST, privaccessadminlist)
cv.put(COLUMN_PRIV_CHANGE_ADMIN_LIST, privchangeadminlist)
cv.put(COLUMN_PRIV_SEND_EMAIL_REPORT, privsendemailreport)
val whereclause = "$COLUMN_ID=?"
val whereargs = arrayOf(id.toString())
return this.writableDatabase.update(TABLE_NAME, cv, whereclause, whereargs)
}
//Your code
fun update() {
val values = ContentValues()
values.put(COLUMN_USERNAME, "adminszzz")
values.put(COLUMN_PASSWORD, "passwordzzz")
values.put(COLUMN_EMAIL, "test#test.orgzzz")
values.put(COLUMN_PRIV_ACCESS_ADMIN_LIST, false)
values.put(COLUMN_PRIV_CHANGE_ADMIN_LIST, true)
values.put(COLUMN_PRIV_SEND_EMAIL_REPORT, false)
values.put(COLUMN_IS_ACTIVE, true)
val db = this.writableDatabase
db.update(TABLE_NAME, values, "$COLUMN_ID=1", arrayOf())
// or
//db.update(TABLE_NAME, values, "$COLUMN_ID=?", arrayOf("1"))
}
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
}
companion object {
val DBNAME = "mydb"
val DBVERSION = 1
val TABLE_NAME = "mytable"
val COLUMN_ID = BaseColumns._ID
val COLUMN_USERNAME = "username"
val COLUMN_PASSWORD = "password"
val COLUMN_EMAIL = "email"
val COLUMN_LAST_LOGIN = "last_login"
val COLUMN_PRIV_ACCESS_ADMIN_LIST = "priv_access_admin_list"
val COLUMN_PRIV_CHANGE_ADMIN_LIST = "priv_change_admin_list"
val COLUMN_PRIV_SEND_EMAIL_REPORT = "priv_send_email_report"
val COLUMN_IS_ACTIVE = "is_active"
}
}
And an Activity to invoke the functions MainAvctivity.kt :-
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
var dbhlpr = DBHelper(this)
dbhlpr = DBHelper(this)
dbhlpr.add("admin", "password", "test#test.com", true, true, true, true)
dbhlpr.logAll()
dbhlpr.updateById(1, "adminssss", "passwordsss", "test#test.org", false, true, false, true)
dbhlpr.logAll()
dbhlpr.update();
dbhlpr.logAll();
}
}
Result
When run the following is output to the log :-
2019-05-17 16:12:07.182 18164-18164/aso.so56179532update D/LOGDATA: Row is 0
UserName is :admin
Pasword is :password
Email is :test#test.com
PRIVACCESSAL is true
PRIVCHGAL is true
PRIVSNDEMAIL is true
2019-05-17 16:12:07.184 18164-18164/aso.so56179532update D/LOGDATA: Row is 0
UserName is :adminssss
Pasword is :passwordsss
Email is :test#test.org
PRIVACCESSAL is false
PRIVCHGAL is true
PRIVSNDEMAIL is false
2019-05-17 16:12:07.186 18164-18164/aso.so56179532update D/LOGDATA: Row is 0
UserName is :adminszzz
Pasword is :passwordzzz
Email is :test#test.orgzzz
PRIVACCESSAL is false
PRIVCHGAL is true
PRIVSNDEMAIL is false
i.e. There are 3 lots, each showing the single row from the database. The second two show that the data has been updated accordingly.
It seems you haven't closed the database by calling db.close() method after updating operation.
Closing the connection flushes the changes you've made, otherwise, the engine waits for the flush period before doing it. It's a good idea to close the connection when you're done using it to ensure that your changes actually go to the store. A power loss after a write and before a flush will lose data.
I have an SQlite data base in an android app developted in kotlin. In this data base I store objects of this class
class Device_info
class Device_info {
var id : Int = 0
var name : String = ""
constructor(id : Int, name: String){
this.id = id
this.name = name
}
}
Now in the id variable I want to store the raw_id that the data base will automaticaly give. I have found in some tutorials how to create a data base handler and I have made it like this
data base handler class
import android.content.ContentValues
import android.content.Context
import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteOpenHelper
private const val DATABASE_NAME = "Devices_db"
private const val TABLE_NAME = "Devices"
private const val RAW_ID = "raw_id"
private const val COLUMN_NAME = "name"
private const val COLUMN_ID = "id"
class DataBaseHandler(var context: Context) : SQLiteOpenHelper(context, DATABASE_NAME, null, 1) {
override fun onCreate(db: SQLiteDatabase?) {
val createTable = "CREATE TABLE " + TABLE_NAME + "(" + RAW_ID +
" INTEGER PRIMARY KEY, " + COLUMN_NAME + " TEXT, " +
COLUMN_ID + "INTEGER)"
db?.execSQL(createTable)
}
override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {}
fun insertData(device: Device_info){
val db = this.writableDatabase
val cv = ContentValues()
cv.put(COLUMN_ID, device.id)
cv.put(COLUMN_NAME, device.name)
db.insert(TABLE_NAME, null, cv)
db.close()
}
fun readData() : MutableList<Device_info>{
val list : MutableList<Device_info> = ArrayList()
val db = this.readableDatabase
val query = "Select * from " + TABLE_NAME
val result = db.rawQuery(query, null)
if(result.moveToFirst()){
do{
val device = Device_info()
device.id = result.getString(result.getColumnIndex(COLUMN_ID)).toInt()
device.name = result.getString(result.getColumnIndex(COLUMN_NAME)
list.add(device)
}while(result.moveToNext())
}
result.close()
db.close()
return list
}
fun UpdateId(device: Device_info){
val db = this.readableDatabase
val cv = ContentValues()
cv.put(COLUMN_ID, device.id)
db.update(TABLE_NAME, cv, "id = " + device.id, null)
db.close()
}
fun UpdateName(device: Device_info){
val db = this.readableDatabase
val cv = ContentValues()
cv.put(COLUMN_NAME, device.name)
cv.put(COLUMN_ID, device.id)
db.update(TABLE_NAME, cv, "id = " + device.id, null)
db.close()
}
fun deleteData(device: Device_info){
val db = this.writableDatabase
val cv = ContentValues()
cv.put(COLUMN_ID, device.id)
cv.put(COLUMN_NAME, device.name)
db.delete(TABLE_NAME, "id = " + device.id, null)
db.close()
}
}
So after I create an object by passing in the constructor the name and as an id -1, because at the time I don't know the raw_id as I haven't added the object in the data base, I call the function insertData and the object is succesfully stored in the data base but the column id contains -1 to all elemnts. My question is how can I copy the raw_id column in the id column?
Why have two columns that are storing exactly the same value? Unless you are then going to manipulate id's which would not be recommended.
Accessing just the one column raw_id would be more efficient. It wouldn't waste space, it would allow more data to be cached and so on.
I guess the clue as to your intention is in because at the time I don't know the raw_id as I haven't added the object in the data base In that you basically want to know what the id is. The following is how you could retrieve the id (raw_id) :-
You retrieve the value returned from the insert and return that from the insertData method.
Something like :-
fun insertData(device: Device_info): Long{
val db = this.writableDatabase
val cv = ContentValues()
cv.put(COLUMN_ID, device.id)
cv.put(COLUMN_NAME, device.name)
val rv = db.insert(TABLE_NAME, null, cv)
db.close()
return rv
}
I hope to define a not null field for a table of SQLite when I use Anko in Kotlin.
But DBRecordTable.Category to TEXT NOT NULL is wrong ,how can I fix it?
Code
implementation "org.jetbrains.anko:anko-sqlite:$anko_version"
override fun onCreate(db: SQLiteDatabase) {
db.createTable( DBRecordTable.TableNAME , true,
DBRecordTable._ID to INTEGER + PRIMARY_KEY+ AUTOINCREMENT,
DBRecordTable.Category to TEXT NOT NULL, //It's wrong
DBRecordTable.Content to TEXT,
DBRecordTable.IsFavorite to INTEGER +DEFAULT("0"),
DBRecordTable.IsProtected to INTEGER +DEFAULT("0"),
DBRecordTable.CreatedDate to INTEGER
)
}
By taking a look at sqlTypes.kt we can find that the not null constraint is defined as following:
val NOT_NULL: SqlTypeModifier = SqlTypeModifierImpl("NOT NULL")
So your code should be:
override fun onCreate(db: SQLiteDatabase) {
db.createTable( DBRecordTable.TableNAME , true,
DBRecordTable._ID to INTEGER + PRIMARY_KEY + AUTOINCREMENT,
DBRecordTable.Category to TEXT + NOT_NULL,
DBRecordTable.Content to TEXT,
DBRecordTable.IsFavorite to INTEGER + DEFAULT("0"),
DBRecordTable.IsProtected to INTEGER + DEFAULT("0"),
DBRecordTable.CreatedDate to INTEGER
)
}
We used these lines of code and it works great table created
private val dbName = THE_PATH +"JSANotes.db"
private val dbTable = "Notes"
private val colId = "Id"
private val colTitle = "Title"
private val colContent = "Content"
private val dbVersion = 1
private val CREATE_TABLE_SQL = "CREATE TABLE IF NOT EXISTS " + dbTable + " (" + colId + " INTEGER PRIMARY KEY," + colTitle + " TEXT, " + colContent + " TEXT NOT NULL);"
private var db: SQLiteDatabase? = null
init {
val dbHelper = DatabaseHelper(context)
db = dbHelper.writableDatabase
}
This site will help with a lot of SQLite questions LINK
We do not use the NOT NULL we do this in place of NOT NULL
if(edtContent.text.toString().equals("")){
error("ENTER Content")
edtContent.requestFocus()
return#setOnClickListener
}
You can also test for length the error message shows in a Text View at the bottom of the Activity with this code
fun error(msg:String){
object : CountDownTimer(4000, 1000) {
override fun onTick(millisUntilFinished: Long) {
tvError.visibility = View.VISIBLE
tvError.setText(msg)
}
override fun onFinish() {
tvError.visibility = View.INVISIBLE
tvError.setText("")
}
}.start()
}