如何 SELECT * FROM table WHERE month AND year in SQLite database by rawQuery(query, args)?

How to SELECT * FROM table WHERE month AND year in SQLite database by rawQuery(query, args)?

我试图 select table 中“月”和“年”相同的所有列。 方法 rawQuery(query,args) 接收一个字符串 [] 数组,其中一个查询将 camps 替换为“?”。

这是我的一些尝试:

"SELECT * FROM EXPENSES WHERE strftime('%m', EXPENSE_DATE)=" + month + " AND strftime('%y',EXPENSE_DATE) =" + year; 

"SELECT * FROM EXPENSES WHERE strftime('%Y/%m', 'EXPENSE_DATE')  =" + year + "/" + month;

最后一个是“?”用有问题的方法替换参数:

String[] selectionArgs = new String[]{String.valueOf(year), String.valueOf(month)};

Cursor cursor = database.rawQuery("SELECT * FROM expenses WHERE expense_date >='?-?-01' AND expense_date <='?-?-31'", selectionArgs);

最后问题再次出现后,我发现问题是视图的对象给出了一个日期,而系统给出了另一种格式。

基本上我有一个 CALENDARVIEW,它给我数据格式(“00-0-00”),如果变量为空,程序将获得系统日期,它给我日期格式(“00 -00-00")

填充空日期的代码是这样的:

//Get the default TIMEZONE
calendar = Calendar.getInstance();
//Set the format date
simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
date = simpleDateFormat.format(calendar.getTime());

日历视图是这样的:

calendarView.setOnDateChangeListener(new CalendarView.OnDateChangeListener() {
            @Override
            public void onSelectedDayChange(@NonNull CalendarView view, int year, int month, int dayOfMonth) {

                    date = year + "-" + (month + 1) + "-" + dayOfMonth;//the Time will be blanck

            }
        });

解决方案是:

calendarView.setOnDateChangeListener(new CalendarView.OnDateChangeListener() {
    @Override
    public void onSelectedDayChange(@NonNull CalendarView view, int year, int month, int dayOfMonth) {
        // the date was being save as 00-0-00 instead of 00-00-00
        if (month >10) {
            date = year + "-" + (month + 1) + "-" + dayOfMonth;//the Time will be blanck
        }else {
            date = year + "-0" + (month + 1) + "-" + dayOfMonth;//the Time will be blanck
        }
    

  }
});

并且 android 中的数据库刚刚使用 strf:

String[] selectionArgs = new String[]{String.valueOf(year), String.valueOf(month)};
String sql = "SELECT * FROM EXPENSES WHERE "+
             "strftime('%Y', EXPENSE_DATE) = ? AND strftime('%m', EXPENSE_DATE) + 0 = ? + 0"; 
Cursor c = db.rawQuery(sql, selectionArgs); 

到此为止,感谢您的帮助!

你的第一次尝试很危险。这将打开您的应用程序以进行 SQL 注入攻击。对于只有一个用户的本地数据库,这可能不是什么大问题。但是你应该养成在第二个查询中使用绑定参数的习惯。

问题是您只能使用 ? 作为 整个 值的占位符,因此您的查询应该是:

String query = "SELECT * FROM expenses WHERE expense_date >= ? AND expense_date <= ?"

现在您需要构建日期对象或格式化字符串作为参数传递:

String begin = year + "-" + month + "-01";
String end = year + "-" + month + "-31";

最后执行查询:

String selectionArgs = new String[]{begin, end};
Cursor cursor = database.rawQuery(query, selectionArgs);

或者,您可以在此处使用 BETWEEN 关键字来代替两个显式不等式比较:

String query = "SELECT * FROM expenses WHERE expense_date BETWEN ? AND ?"

始终在 sql 语句中使用 ? 占位符,并在 rawQuery() 的第二个参数中将参数作为数组传递。
这是推荐的安全方法。

我假设变量 yearmonth 是整数,这就是为什么您使用 String.valueOf() 将它们转换为字符串数组中的字符串。
我还假设列 EXPENSES 具有正确的格式 YYYY-MM-DD 以便 strftime() 将成功提取年份和月份。

问题是,当您使用 strftime() 提取月份时,它会作为字符串返回:如果需要,用 0 填充的数字,比如 05
但是如果你传递的 month 的值是 1 位整数,比如 5WHERE 子句中的条件将变为:

WHERE '05' = '5'

其中 returns false.
要解决此问题,您需要通过添加 0.
strftime() 的结果隐式转换为整数 对于年份,因为数值都是4位数,所以不存在这个问题,但是记得在strftime()里面使用'%Y'格式,代表的是4位数的年份,而不是'%y'代表两位数的年份。

所以这样写你的代码:

String[] selectionArgs = new String[]{String.valueOf(year), String.valueOf(month)};
String sql = "SELECT * FROM EXPENSES WHERE "+
             "strftime('%Y', EXPENSE_DATE) = ? AND strftime('%m', EXPENSE_DATE) + 0 = ? + 0"; 
Cursor c = db.rawQuery(sql, selectionArgs);