数据库相关
一、在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 10002.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;- 在这里,主查询通过JOIN操作连接了
farmer_shop表和前面定义的DateRangeCTE。 - 它选择那些
pub_date与DateRange中的date_value相匹配的记录。 - 最后,结果按照
pub_date降序排列,并限制输出最多1000条记录(LIMIT 1000)。
这种方法适用于支持递归CTE的数据库系统,比如MySQL 8.0及以上版本、PostgreSQL等。需要注意的是,如果没有对递归深度进行控制,理论上这种递归可能会无限进行下去。不过,在这个例子中,由于每次迭代都会减少一天,最终总会到达有数据的日期或者到达某个无法再减的日期边界(如表中最早的日期)。因此,实际上不会发生无限递归的情况。
