android.database.sqlite.SQLiteConstraintException:唯一约束失败
当我想向sqlite添加数据时,会弹出此错误。以前在SQLite中已经有一个数据。你能帮我解决我的问题吗?android.database.sqlite.SQLiteConstraintException:唯一约束失败,android,sqlite,Android,Sqlite,当我想向sqlite添加数据时,会弹出此错误。以前在SQLite中已经有一个数据。你能帮我解决我的问题吗? 为什么在设置id自动递增时插入id 删除args.put(ID_MOVIE,movieFavorite.getId())来自插入查询,如下所示 public long insertMovie(MovieFav movieFavorite) { ContentValues args = new ContentValues(); args.put(TITLE,
为什么在设置id自动递增时插入id
删除args.put(ID_MOVIE,movieFavorite.getId())代码>来自插入查询,如下所示
public long insertMovie(MovieFav movieFavorite) {
ContentValues args = new ContentValues();
args.put(TITLE, movieFavorite.getTitle());
args.put(OVERVIEW, movieFavorite.getOverview());
args.put(RELEASE_DATE, movieFavorite.getRelease_date());
args.put(VOTE_AVERAGE, movieFavorite.getVote_average());
args.put(POSTER_PATH, movieFavorite.getPoster_path());
return sqLiteDatabase.insert(DATABASE_TABLE, null, args);
}
您可能不希望有这样一行:-
args.put(ID_MOVIE, movieFavorite.getId());
在插入电影方法中
如果没有该行,将自动生成id(1、2、3(可能))
如果确实包含了上述行,则会尝试插入,但如果该值已在该列的其他行中使用,则会出现唯一约束冲突。也就是说,主键必须是唯一的,因此即使没有编码唯一,它们也是唯一的,就好像编码唯一一样(即暗示了唯一约束)
注;您很可能不需要自动递增,+”(%s INTEGER主键,++
仍将自动生成id,但效率更高。根据:-
AUTOINCREMENT关键字会带来额外的CPU、内存、磁盘空间和磁盘I/O开销,如果不严格需要,应该避免使用。通常不需要
根据评论:-
如果未添加args.put(ID_MOVIE,movieFavorite.getId()),则数据将被复制
下面是一个例子:-
DbHelper.java
活动中的代码
日志中的结果:-
如上所述,始终尝试添加4行,如果再次运行,则:-
2019-09-28 20:00:52.454 7188-7188/aso.asoinmemorysbtofiledb D/MOVIELIST: Title is Gone with the wind
ID is 1
Overview is
It blows
2019-09-28 20:00:52.454 7188-7188/aso.asoinmemorysbtofiledb D/MOVIELIST: Title is The Magnificent Seven
ID is 2
Overview is
Magnificent
2019-09-28 20:00:52.454 7188-7188/aso.asoinmemorysbtofiledb D/MOVIELIST: Title is The Lord of the Rings
ID is 3
Overview is
I'll ring you about this one
2019-09-28 20:00:52.454 7188-7188/aso.asoinmemorysbtofiledb D/MOVIELIST: Title is War of the Worlds
ID is 4
Overview is
Alien to me
2019-09-28 20:00:52.454 7188-7188/aso.asoinmemorysbtofiledb D/MOVIELIST: Title is Gone with the wind
ID is 5
Overview is
It blows
2019-09-28 20:00:52.454 7188-7188/aso.asoinmemorysbtofiledb D/MOVIELIST: Title is The Magnificent Seven
ID is 6
Overview is
Magnificent
2019-09-28 20:00:52.454 7188-7188/aso.asoinmemorysbtofiledb D/MOVIELIST: Title is The Lord of the Rings
ID is 7
Overview is
I'll ring you about this one
2019-09-28 20:00:52.455 7188-7188/aso.asoinmemorysbtofiledb D/MOVIELIST: Title is War of the Worlds
ID is 8
Overview is
Alien to me
i、 e.添加了相同的行,但有其他id(这次为5-8)
没有重复的电影
如果您想要的是不复制数据,比如整个电影,这样就不会添加5-8,那么您可以创建一个适用于您不想复制的数据的唯一约束。id将永远不会被复制。从电影信息的角度来看,就数据而言,它不能也没有用处(从数据库的角度来看,id非常有用)
如果已经有一部电影具有相同的标题和相同的发行日期,则假设您永远不希望添加电影,那么您可以使电影标题和电影发行日期的组合唯一
e、 g.对于上述内容,您创建表格的代码可以是(见注释):-
- 请注意,
行是不需要的,添加它是为了显示SQL生成的内容,如传递给SQLite的内容Log.d(“ALTINSERTSQL”,sqlstmnt.toString());
在电影(标题、概述、发行日期、投票平均数、照片)中插入或忽略值(?、、?、?)
- 's由SQLite API绑定(与使用String.format类似),因此使用bindallargsassstrings允许SQLite将每个?替换为适当的值。这会阻止SQLInjection
mMyDBHlpr = new DbHelper(this); //Instantiate Database Helper
// Add some Movies WITHOUT specifying ID
mMyDBHlpr.insertMovie(new MovieFav("Gone with the wind","It blows","2019-01-01","medium","//posters/movies/gwtw"));
mMyDBHlpr.insertMovie(new MovieFav("The Magnificent Seven","Magnificent","2019-10-01","medium","//posters/movies/tms"));
mMyDBHlpr.insertMovie(new MovieFav("The Lord of the Rings","I'll ring you about this one","2015-12-01","great","//posters/movies/lotrp1"));
mMyDBHlpr.insertMovie(new MovieFav("War of the Worlds","Alien to me","2010-01-01","ok","//posters/movies/wotw"));
mMyDBHlpr.insertMovieAlternative(new MovieFav("Gone with the wind","It blows","2019-01-01","medium","//posters/movies/gwtw"));
mMyDBHlpr.insertMovieAlternative(new MovieFav("The Magnificent Seven","Magnificent","2019-10-01","medium","//posters/movies/tms"));
mMyDBHlpr.insertMovieAlternative(new MovieFav("The Lord of the Rings","I'll ring you about this one","2015-12-01","great","//posters/movies/lotrp1"));
mMyDBHlpr.insertMovieAlternative(new MovieFav("War of the Worlds","Alien to me","2010-01-01","ok","//posters/movies/wotw"));
// Output Movies information to the log INCLUDING ID
mMyDBHlpr.logAllMovies();
这会尝试添加同一组电影,但第二批不会添加,因为为电影标题Moview发行日期组合添加了唯一约束,但日志中不包含异常消息(没有异常,因为如果发生冲突,INSERT或IGNORE将充当noop(不执行任何操作))
日志将改为:-
2019-09-28 20:52:06.304 D/ALTINSERTSQL: SQLiteProgram: INSERT OR IGNORE INTO movie(title,overview,release_date,vote_average,photo) VALUES (?,?,?,?,?)
2019-09-28 20:52:06.305 I/chatty: uid=10419(aso.asoinmemorysbtofiledb) identical 2 lines
2019-09-28 20:52:06.306 D/ALTINSERTSQL: SQLiteProgram: INSERT OR IGNORE INTO movie(title,overview,release_date,vote_average,photo) VALUES (?,?,?,?,?)
2019-09-28 20:52:06.307 D/MOVIELIST: Title is Gone with the wind
ID is 1
Overview is
It blows
2019-09-28 20:52:06.307 D/MOVIELIST: Title is The Magnificent Seven
ID is 2
Overview is
Magnificent
2019-09-28 20:52:06.307 D/MOVIELIST: Title is The Lord of the Rings
ID is 3
Overview is
I'll ring you about this one
2019-09-28 20:52:06.307 D/MOVIELIST: Title is War of the Worlds
ID is 4
Overview is
Alien to me
如果未添加args.put(ID\u MOVIE,movieFavorite.getId()),则数据将被复制。如果args.put(ID\u MOVIE,movieFavorite.getId())如果不添加;,则数据将被复制。@SatyaRac如果不提供值,即no
args.put
,则基础SQL将不提供值,并且由于该列是rowid列的别名,则该值将自动生成并唯一。根据插入,如果rowid或INTEGER主键列不显式如果给定一个值,则该值将自动填充一个未使用的整数,通常比当前使用的最大ROWID多一个。无论是否使用AUTOINCREMENT关键字,这都是正确的。@SatyaRac,我相信我现在理解了,希望答案的其他部分能够解决这些问题(简而言之,这并不是真正的问题,这些消息只是由于异常被捕获、处理和报告而没有添加和产生重复项的信息)。
public class MainActivity extends AppCompatActivity {
DbHelper mMyDBHlpr;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mMyDBHlpr = new DbHelper(this); //Instantiate Database Helper
// Add some Movies WITHOUT specifying ID
mMyDBHlpr.insertMovie(new MovieFav("Gone with the wind","It blows","2019-01-01","medium","//posters/movies/gwtw"));
mMyDBHlpr.insertMovie(new MovieFav("The Magnificent Seven","Magnificent","2019-10-01","medium","//posters/movies/tms"));
mMyDBHlpr.insertMovie(new MovieFav("The Lord of the Rings","I'll ring you about this one","2015-12-01","great","//posters/movies/lotrp1"));
mMyDBHlpr.insertMovie(new MovieFav("War of the Worlds","Alien to me","2010-01-01","ok","//posters/movies/wotw"));
// Output Movies information to the log INCLUDING ID
mMyDBHlpr.logAllMovies();
}
2019-09-28 19:51:52.242 7088-7088/aso.asoinmemorysbtofiledb D/MOVIELIST: Title is Gone with the wind
ID is 1
Overview is
It blows
2019-09-28 19:51:52.243 7088-7088/aso.asoinmemorysbtofiledb D/MOVIELIST: Title is The Magnificent Seven
ID is 2
Overview is
Magnificent
2019-09-28 19:51:52.243 7088-7088/aso.asoinmemorysbtofiledb D/MOVIELIST: Title is The Lord of the Rings
ID is 3
Overview is
I'll ring you about this one
2019-09-28 19:51:52.243 7088-7088/aso.asoinmemorysbtofiledb D/MOVIELIST: Title is War of the Worlds
ID is 4
Overview is
Alien to me
2019-09-28 20:00:52.454 7188-7188/aso.asoinmemorysbtofiledb D/MOVIELIST: Title is Gone with the wind
ID is 1
Overview is
It blows
2019-09-28 20:00:52.454 7188-7188/aso.asoinmemorysbtofiledb D/MOVIELIST: Title is The Magnificent Seven
ID is 2
Overview is
Magnificent
2019-09-28 20:00:52.454 7188-7188/aso.asoinmemorysbtofiledb D/MOVIELIST: Title is The Lord of the Rings
ID is 3
Overview is
I'll ring you about this one
2019-09-28 20:00:52.454 7188-7188/aso.asoinmemorysbtofiledb D/MOVIELIST: Title is War of the Worlds
ID is 4
Overview is
Alien to me
2019-09-28 20:00:52.454 7188-7188/aso.asoinmemorysbtofiledb D/MOVIELIST: Title is Gone with the wind
ID is 5
Overview is
It blows
2019-09-28 20:00:52.454 7188-7188/aso.asoinmemorysbtofiledb D/MOVIELIST: Title is The Magnificent Seven
ID is 6
Overview is
Magnificent
2019-09-28 20:00:52.454 7188-7188/aso.asoinmemorysbtofiledb D/MOVIELIST: Title is The Lord of the Rings
ID is 7
Overview is
I'll ring you about this one
2019-09-28 20:00:52.455 7188-7188/aso.asoinmemorysbtofiledb D/MOVIELIST: Title is War of the Worlds
ID is 8
Overview is
Alien to me
private static final String DATABASE_NAME = "movielist";
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_TABLE = DbContract.TABLE_MOVIE;
private static final String SQL_CREATE_TABLE_MOVIE_FAV = String.format("CREATE TABLE %s"
+ " (%s INTEGER PRIMARY KEY AUTOINCREMENT," +
" %s TEXT NOT NULL," +
" %s TEXT NOT NULL," +
" %s TEXT NOT NULL," +
" %s TEXT NOT NULL," +
" %s TEXT NOT NULL" + //<<<<<<<<<< REMOVED CLOSING PARENTHESIS
/* ADDED the UNQIUE CONSTRAINT ON THE Title and release date */
", UNIQUE ("
+ DbContract.MovieListFavorite.MOVIE_TITLE +
"," + DbContract.MovieListFavorite.MOVIE_RELEASE_DATE
+ ")" + // END Of THE UNIQUE CONSTRAINT
")", //<<<<<<<<<< END OF CHANGES FOR ADDING UNIQUE constraint
/**
* NOTE AS THE SCHEMA HAS CHANGED THE DATABASE NEEDS TO BE DELETED (altering is possible but harder)
* THEREFORE TO INTRODUCE CHANGES >>>>>>>>>>UNINSTALL THE APP AND THEN RERUN<<<<<<<<<<.
*/
DATABASE_TABLE,
DbContract.MovieListFavorite.MOVIE_ID,
DbContract.MovieListFavorite.MOVIE_TITLE,
DbContract.MovieListFavorite.MOVIE_OVERVIEW,
DbContract.MovieListFavorite.MOVIE_RELEASE_DATE,
DbContract.MovieListFavorite.MOVIE_PHOTO,
DbContract.MovieListFavorite.MOVIE_VOTE_AVERAGE
);
public long insertMovieAlternative(MovieFav movieFavorite) {
String insertSQL = "INSERT OR IGNORE INTO " + DATABASE_TABLE +
"(" +
DbContract.MovieListFavorite.MOVIE_TITLE + "," +
DbContract.MovieListFavorite.MOVIE_OVERVIEW + "," +
DbContract.MovieListFavorite.MOVIE_RELEASE_DATE + "," +
DbContract.MovieListFavorite.MOVIE_VOTE_AVERAGE + "," +
DbContract.MovieListFavorite.MOVIE_PHOTO +
") VALUES (?,?,?,?,?)";
SQLiteStatement sqlstmnt = sqLiteDatabase.compileStatement(insertSQL);
sqlstmnt.bindAllArgsAsStrings(new String[]{
movieFavorite.getTitle(),
movieFavorite.getOverview(),
movieFavorite.getRelease_date(),
movieFavorite.getVote_average(),
movieFavorite.getPoster_path()
});
Log.d("ALTINSERTSQL",sqlstmnt.toString());
return sqlstmnt.executeInsert();
}
mMyDBHlpr = new DbHelper(this); //Instantiate Database Helper
// Add some Movies WITHOUT specifying ID
mMyDBHlpr.insertMovie(new MovieFav("Gone with the wind","It blows","2019-01-01","medium","//posters/movies/gwtw"));
mMyDBHlpr.insertMovie(new MovieFav("The Magnificent Seven","Magnificent","2019-10-01","medium","//posters/movies/tms"));
mMyDBHlpr.insertMovie(new MovieFav("The Lord of the Rings","I'll ring you about this one","2015-12-01","great","//posters/movies/lotrp1"));
mMyDBHlpr.insertMovie(new MovieFav("War of the Worlds","Alien to me","2010-01-01","ok","//posters/movies/wotw"));
mMyDBHlpr.insertMovieAlternative(new MovieFav("Gone with the wind","It blows","2019-01-01","medium","//posters/movies/gwtw"));
mMyDBHlpr.insertMovieAlternative(new MovieFav("The Magnificent Seven","Magnificent","2019-10-01","medium","//posters/movies/tms"));
mMyDBHlpr.insertMovieAlternative(new MovieFav("The Lord of the Rings","I'll ring you about this one","2015-12-01","great","//posters/movies/lotrp1"));
mMyDBHlpr.insertMovieAlternative(new MovieFav("War of the Worlds","Alien to me","2010-01-01","ok","//posters/movies/wotw"));
// Output Movies information to the log INCLUDING ID
mMyDBHlpr.logAllMovies();
2019-09-28 20:52:06.304 D/ALTINSERTSQL: SQLiteProgram: INSERT OR IGNORE INTO movie(title,overview,release_date,vote_average,photo) VALUES (?,?,?,?,?)
2019-09-28 20:52:06.305 I/chatty: uid=10419(aso.asoinmemorysbtofiledb) identical 2 lines
2019-09-28 20:52:06.306 D/ALTINSERTSQL: SQLiteProgram: INSERT OR IGNORE INTO movie(title,overview,release_date,vote_average,photo) VALUES (?,?,?,?,?)
2019-09-28 20:52:06.307 D/MOVIELIST: Title is Gone with the wind
ID is 1
Overview is
It blows
2019-09-28 20:52:06.307 D/MOVIELIST: Title is The Magnificent Seven
ID is 2
Overview is
Magnificent
2019-09-28 20:52:06.307 D/MOVIELIST: Title is The Lord of the Rings
ID is 3
Overview is
I'll ring you about this one
2019-09-28 20:52:06.307 D/MOVIELIST: Title is War of the Worlds
ID is 4
Overview is
Alien to me