【问题标题】:How to SELECT * FROM table WHERE month AND year in SQLite database by rawQuery(query, args)?如何通过 rawQuery(query, args) 在 SQLite 数据库中从表 WHERE 月份和年份中选择 *?
【发布时间】:2021-09-14 13:31:35
【问题描述】:

我试图选择表中“月”和“年”相同的所有列。 rawQuery(query,args) 方法接收一个 string[] 数组,其中一个查询将营地替换为“?”。

这是我的一些尝试:

"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;

最后一个带有“?”用相关方法替换 args:

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);

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

基本上我有一个 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); 

谢谢大家的帮助!

【问题讨论】:

    标签: java android sqlite android-sqlite strftime


    【解决方案1】:

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

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

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

    WHERE '05' = '5'
    

    返回false
    要解决这个问题,您需要通过添加 0strftime() 的结果隐式转换为整数。
    对于年份,由于值始终为 4 位,因此没有这样的问题,但请记住在 strftime() 中使用 '%Y' 格式,表示 4 位数年份,而不是 '%y' 表示 2 位数年。

    所以这样写你的代码:

    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); 
    

    【讨论】:

    • 我试过没有成功,代码也没有显示任何错误。我的日期格式是 ('yyy-MM-dd');
    • @Matheus 我在我的代码中错过了+0。我编辑了。
    【解决方案2】:

    您的第一次尝试很危险。这将打开您的应用程序以进行 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 ?"
    

    【讨论】:

    • 感谢您的帮助!
    猜你喜欢
    • 2017-11-09
    • 1970-01-01
    • 2015-04-03
    • 2015-12-26
    • 1970-01-01
    • 1970-01-01
    • 2017-07-12
    • 2018-01-23
    • 1970-01-01
    相关资源
    最近更新 更多