将一系列日期存储在数据库中的一行或单独的表中

Posted

技术标签:

【中文标题】将一系列日期存储在数据库中的一行或单独的表中【英文标题】:Storing a range of dates in one row in database or in seperate table 【发布时间】:2021-07-01 04:19:16 【问题描述】:

我正在尝试使用 jquery datepicker 制作汽车预订系统。我有日期选择器,我在数据库中有日期(手动插入 WAMP SERVER phpMyAdmin),将这些日期突出显示为预先预订的日期(鼠标悬停在 css 中禁用光标),因此您无法预订这些日期。

我正在组装我的所有零件,但在如何存储日期的最后一点上卡住了。从我读到的内容看来,将一堆日期存储在一行中是不行的(而且我还没有设法做到这一点)。

    那么,我是否应该将每个客户端的开始和结束日期存储在一个数据库表行中,并在页面/日期选择器加载时生成中间日期? 如果采用这种方法,我如何获取然后将每一行(许多客户)日期连接在一起? 或者我应该生成中间日期,然后在日期选择器选择开始和结束时将所有日期与客户端 ID 一起存储在单独的表中?

有人可以用正确的方法和 php 代码帮助我到达那里。我已经有 mysqli 连接等。

目前我的数据库列是start_date & end_date in tabledates_from_to。我的日期选择器使用这种格式 2021-04-15 并且需要的数组看起来像这样 '2021-04-15','2021-04-16','2021-04-17' 来突出显示日期。

【问题讨论】:

【参考方案1】:

您的客户/客户与预订之间似乎存在 1:n 的关系。所以是的,您应该根据database normalization 规则将它们存储在单独的表中。

假设您有一个表 clients(主键 client_id)和 bookings,它替换了您的 dates_from_to 表(使用外键 client_id),您可以执行以下 JOIN:

SELECT * 
  FROM clients
  JOIN bookings 
 USING (client_id) 
 WHERE booking_date = '2021-04-05'

对于下一部分,我将采用示例数组。这是每天插入一行的示例代码:

$dates = ['2021-04-15','2021-04-16','2021-04-17'];

// $pdo contains a connected DB instance
$stmt = $pdo->prepare('INSERT INTO bookings (client_id, booking_date) VALUES (?, ?)');

foreach ($dates as $day) 
    $stmt->execute([1, $day]);

作为替代方案,您可以使用该期间的第一天和最后一天并将所有内容存储在一行中,方法是将 booking_date 列替换为 start_dateend_date

这是带有 mysqli 和开始/结束日期的版本(来自docs):

$mysqli = new mysqli("example.com", "user", "password", "database");

$mysqli->prepare('INSERT INTO bookings (client_id, start_date, end_date) VALUES (?, ?, ?)');

// iss means (i)nteger, (s)tring and (s)tring parameter
$stmt->bind_param('iss', 1, '2021-04-15', '2021-04-17'); 
$stmt->execute();

希望这能让你继续前进。

【讨论】:

谢谢@jumper85,我需要每个 booking 日期,以便在日期选择器中突出显示已预订的日期,因此您是说生成日期并插入它们进入预订表?如果开始日期是 2021-04-05 并且结束日期是 2021-04-15 将有 11 天/日期我该如何进行编码并插入 DB 预订表? 啊,我明白了,所以你想要每天一个预订条目,不管是一个人几天的预订?另一种方法是有一个记录开始和结束日期。 我稍微调整了答案,如果我假设的方向正确,请告诉我;-) 谢谢@jumper85。我想我喜欢start_dateend_date,但我的速度很快。我在@MarkBaker 的***.com/a/18513846/4975737> 处找到了这段代码,但无法将其转换为变量或转换为jquery datepicker 喜欢的代码。无论是用于日期选择器还是将其存储在单独的行中,我都在解决这个问题时遇到了很大的问题。 您提到您的日期选择器需要2021-04-05 格式,因此只需为此$date->format('Y-m-d'); 使用格式并获取$date,您可以简单地根据您在DB $date = new DateTime($dbDate); 中的值创建新对象跨度> 【参考方案2】:

大约一个月后,我的日期选择器开始工作,将数据库中的所有日期存储在各自的行中。

它从两个日期选择器中选择开始日期和结束日期。

创建/生成其间的所有日期,然后将所有这些单独的日期插入到数据库中,每个日期在 PHP 中它自己的行中。

然后重定向到同一页面并突出显示所有数据库日期并禁用它们,因此没有人可以选择已经预订的日期。

我已经从这个站点复制了不同的代码并对其进行了一些操作,目前我对混合结果非常满意。

这是在 WAMP 服务器上运行的。

下面是我的代码,可以帮助像我这样的其他业余爱好者。

<?php

$servername = "localhost:3308";
$username = "root";
$password = "";
$dbname = "datepicker_test_outputs";

// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) 
die("Connection failed: " . $conn->connect_error);



$sql = "SELECT date FROM insert_datesarray";
$result = $conn->query($sql);

if ($result->num_rows > 0) 
$for_JS_date = null;

// output data of each row
while($row = $result->fetch_assoc()) 
    
    $php_array_dates = date('Y-m-d',strtotime($row["date"]));
    
        $for_JS_date .= "'".$php_array_dates."'".",";
        
            $correct_date_format = substr($for_JS_date, 0, -1);
            


if($_SERVER["REQUEST_METHOD"]=="POST")

$start_date = $_POST["from"];
$end_date = $_POST["to"];

$dateentry = array();

// populate $dateentry array with dates
while (strtotime($start_date) <= strtotime($end_date)) 
    $dateentry[] =  date("Y-m-d", strtotime($start_date));
    $start_date = date ("Y-m-d", strtotime("+1 day", strtotime($start_date)));
 // end while

// loop through $dateentry and insert each date into database
foreach($dateentry as $entry) 

    $my_inserted_dates =("INSERT INTO insert_datesarray 
        (date)  VALUES('$entry')")
        or die(mysqli_error());
        $result = mysqli_query($conn,$my_inserted_dates);

if($result == false)

    echo "<script>alert('BOOKING IS NOT SUCCESS - PLEASE CONTACT ADMINISTRATOR');      </script>";

else

   /* Header location to refresh the page & load booked dates */
   header('Location: '.$_SERVER['PHP_SELF']);



 die;
// end foreach



?> 
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>jQuery UI DatePicker</title>
<link rel="stylesheet" href="//code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css">
<script src="//code.jquery.com/jquery-1.9.1.js"></script>
<script src="//code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<style>
    .ui-highlight .ui-state-default
        background: red !important;
        border-color: red !important;
        color: white !important;
            cursor:not-allowed !important;

    
</style>
<script type="text/javascript" language="javascript">
    var dates = [<?php echo $correct_date_format;?>];       
    /*var dates = ['2021-04-05','2021-04-15','2021-04-25','2021-04-30'];*/
    jQuery(function()
        jQuery('input[id=from]').datepicker(
            dateFormat: 'dd-mm-yy',/*CN  Changes date format. Remove if required  CN*/
            changeMonth : true,
            changeYear : true,
            minDate: 0 ,/*Mindate disables dates before todays date*/
            beforeShowDay : function(date)
                var y = date.getFullYear().toString(); // get full year
                var m = (date.getMonth() + 1).toString(); // get month.
                var d = date.getDate().toString(); // get Day
                if(m.length == 1) m = '0' + m;  // append zero(0) if single digit
                if(d.length == 1) d = '0' + d;  // append zero(0) if single digit
                var currDate = y+'-'+m+'-'+d;
                if(dates.indexOf(currDate) >= 0)
                    return [true, "ui-highlight", 'Date Already Booked'];   
                else
                    return [true];
                                   
            
        );
    )
</script>
<script type="text/javascript" language="javascript">       
    var dates = [<?php echo $correct_date_format;?>];       
    /*var dates = ['2021-04-05','2021-04-15','2021-04-25','2021-04-30'];*/
    jQuery(function()
        jQuery('input[id=to]').datepicker(
            dateFormat: 'dd-mm-yy',/*CN  Changes date format. Remove if required  CN*/
            changeMonth : true,
            changeYear : true,
            minDate: 0 ,/*Mindate disables dates before todays date*/
            beforeShowDay : function(date)
                var y = date.getFullYear().toString(); // get full year
                var m = (date.getMonth() + 1).toString(); // get month.
                var d = date.getDate().toString(); // get Day
                if(m.length == 1) m = '0' + m;  // append zero(0) if single digit
                if(d.length == 1) d = '0' + d;  // append zero(0) if single digit
                var currDate = y+'-'+m+'-'+d;
                if(dates.indexOf(currDate) >= 0)
                    return [true, "ui-highlight", 'Date Already Booked'];   
                else
                    return [true];
                                   
            
        );
    )
</script>
</head>
<body>
<p id="dateFrom"></p>
<p id="dateTo"></p>
<form action="" name="form1" method="post">
<label for="from">From</label>
<input type="text" id="from" name="from"onchange="getFromDate()">
<label for="to">to</label>
<input type="text" id="to" name="to"onchange="getToDate()">
<input name="book" type="submit" value="Book">
</form> 
</body>
</html>

【讨论】:

警告:您对SQL Injections 持开放态度,应该使用参数化的prepared statements,而不是手动构建查询。它们由PDO 或MySQLi 提供。永远不要相信任何形式的输入!即使您的查询仅由受信任的用户执行,you are still in risk of corrupting your data。 Escaping is not enough! 你有一个错误。 mysqli_error() 需要一个参数。请考虑改为打开错误模式。 How to get the error message in MySQLi?

以上是关于将一系列日期存储在数据库中的一行或单独的表中的主要内容,如果未能解决你的问题,请参考以下文章

SQL 如何对数据库中相同名称的表中数据进行批量修改

如何通过单个查询显示存储在我的表中的两个日期之间的所有日期? [复制]

我可以使用 SQL 将存储为 CSV(逗号分隔值)的表列的内容拆分为新表中的单独行吗?

MySQL为每一行自动存储日期时间

使用flume在两个单独的表中写入hive仓库目录中的数据

pl/sql 存储过程从日期等于存储过程参数的表中进行选择