Skip to content

数据库相关

一、在Java中怎么创建一个存储过程

1 设置JDBC驱动

首先,确保你的项目包含了适合你数据库的JDBC驱动。对于MySQL,你需要包含MySQL Connector/J库。如果你使用的是Maven项目,可以在pom.xml文件中添加以下依赖:

xml
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.26</version> <!-- 请根据需要选择版本 -->
</dependency>

2 创建存储过程

java
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;

public class CreateProcedureExample {

    public static void main(String[] args) {
        // 数据库URL、用户名和密码
        String url = "jdbc:mysql://localhost:3306/yourDatabaseName"; // 替换为你的数据库名
        String user = "root"; // 替换为你的数据库用户名
        String password = "password"; // 替换为你的数据库密码

        // 存储过程创建语句
        String createProcSQL = 
            "CREATE PROCEDURE FindLatestDataWithRecords() BEGIN "
            + "DECLARE latest_date DATE; DECLARE found_records INT DEFAULT 0;"
            + "SET latest_date = CURDATE();"
            + "WHILE found_records = 0 DO "
            + "SELECT COUNT(*) INTO found_records FROM farmer_shop WHERE DATE(pub_date) = latest_date;"
            + "IF found_records = 0 THEN SET latest_date = DATE_SUB(latest_date, INTERVAL 1 DAY); ELSE LEAVE; END IF;"
            + "END WHILE;"
            + "SELECT * FROM farmer_shop WHERE DATE(pub_date) = latest_date;"
            + "END";

        Connection conn = null;
        Statement stmt = null;

        try {
            // 连接到数据库
            conn = DriverManager.getConnection(url, user, password);
            stmt = conn.createStatement();

            // 执行创建存储过程的SQL
            stmt.execute(createProcSQL);

            System.out.println("存储过程创建成功!");

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 关闭资源
            try {
                if (stmt != null) stmt.close();
                if (conn != null) conn.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

二、根据时间日期查找数据库最新的一天数据,最新一天没有就找前一天数据

1 使用存储过程来解决

2 使用回退逻辑利用子查询和条件判断来找到最近有记录的日期

sql
WITH RECURSIVE DateRange AS (
    SELECT MAX(DATE(pub_date)) AS date_value FROM farmer_shop
    UNION ALL
    SELECT DATE_SUB(date_value, INTERVAL 1 DAY)
    FROM DateRange
    WHERE NOT EXISTS (
        SELECT 1 FROM farmer_shop fs WHERE DATE(fs.pub_date) = DateRange.date_value
    )
)
SELECT fs.* FROM farmer_shop fs
JOIN DateRange dr ON DATE(fs.pub_date) = dr.date_value
ORDER BY fs.pub_date DESC LIMIT 1000

2.1 回推逻辑详解

SQL查询使用了递归CTE(Common Table Expression)来查找farmer_shop表中最近有数据的日期,并返回该日期下的所有记录。如果最近的一天没有数据,则回退到前一天,直到找到有数据的那一天为止。

2.1.1 递归CTE定义 (WITH RECURSIVE DateRange AS (...))
  • 初始部分
sql
SELECT MAX(DATE(pub_date)) AS date_value FROM farmer_shop

这一部分首先从farmer_shop表中获取最新的日期(即最大日期),并将其命名为date_value

  • 递归部分
sql
UNION ALL
SELECT DATE_SUB(date_value, INTERVAL 1 DAY)
FROM DateRange
WHERE NOT EXISTS (
    SELECT 1 FROM farmer_shop fs WHERE DATE(fs.pub_date) = DateRange.date_value
)

如果在当前date_value下没有找到任何记录(通过NOT EXISTS子查询检查),则递归地将``date_value`减去一天,并继续这个过程,直到找到有数据的那一天。

2.1.2 主查询
sql
SELECT fs.* 
FROM farmer_shop fs
JOIN DateRange dr ON DATE(fs.pub_date) = dr.date_value
ORDER BY fs.pub_date DESC LIMIT 1000;
  1. 在这里,主查询通过JOIN操作连接了farmer_shop表和前面定义的DateRange CTE。
  2. 它选择那些pub_dateDateRange中的date_value相匹配的记录。
  3. 最后,结果按照pub_date降序排列,并限制输出最多1000条记录(LIMIT 1000)。

这种方法适用于支持递归CTE的数据库系统,比如MySQL 8.0及以上版本、PostgreSQL等。需要注意的是,如果没有对递归深度进行控制,理论上这种递归可能会无限进行下去。不过,在这个例子中,由于每次迭代都会减少一天,最终总会到达有数据的日期或者到达某个无法再减的日期边界(如表中最早的日期)。因此,实际上不会发生无限递归的情况。