避免在一个范围内重复值


avoid duplicating values in a range

注意:"我是这方面的新手。我需要一个mysql查询,将不允许用户在已经存在于数据库的范围内的数字。我在这里处理卡和卡的数量由user1制造将通过创建页面插入之前,他/她开始。虽然user2可以在另一台机器上开始,但没有关于user1从哪里开始的事先信息。例如,如果user2尝试选择从1、2、3、4、5、6到2530开始,应该发生一个触发或错误,以防止它们复制user1已经完成的范围。

根据建议,我在表中有一个"number_from"和一个"number_to"列。在下面的表格中找到我想要达到的目标

还要注意,复制卡应该依赖于job_number,因为作业的唯一标识符是job_number,任何作业都不可能相同。

我以前问过这个问题,但没有明确的解决方案,或者可能是因为我没有编写触发器或存储过程的经验。就像我之前说的"我是一个新手",我的未来取决于这个

id |user_id| number_from | number_to | client | cardtype  | job_number | job_quant |status
1  | smith |      1      |   2530    | queens |inspiration| j290122    | 5000      |nt done
2  | john  |   2531      |   4000    | queens |inspiration| j290122    | 5000      |nt done
4  | kenny |      1      |   1500    |seabirds|   love    | j300011    | 1500      | done
3  | wayne |   4001      |   5000    | queens |inspiration| j290122    | 5000      | done

user_id是一个外键

id | user | password
1  |smith | ********
2  |john  | ********
3  |wayne | ********
4  |kenny | ********
5  |laura | ********

到目前为止,我有一个插入查询添加数据到数据库。

<?php 
if (isset($_POST['submit'])) {
 // process the form
$user_id = (int) $_POST["user_id"];
$number_from = $_POST["number_from"];
$number_to = $_POST["number_to"];
$client = mysql_prep($_POST["client"]);
$cardtype = $_POST["cardtype"];
$job_number = $_POST["job_number"];
$job_quantity = $_POST["job_quantity"];
$status = $_POST["status"];
$query = "INSERT INTO jobs (";
$query .= " user_id, number_from, number_to, client, cardtype, job_number, job_quantity, status";
$query .= ") VALUES (";
$query .= " '{$user_id}', '{$number_from}', '{$number_to}', '{$client}', '{$card_type}', '{$job_number}', '{$job_quantity}', '{$status}'";
$query .= ")";
$result = mysqli_query($connection, $query);
if ($result) {
// success
   $_SESSION["message"] = "job created.";
   redirect_to("manage_job.php"); 
  } else {
// failure  
   $_SESSION["message"] = "job creation failed.";
   redirect_to("new_job.php");
  }  
} 
?>

MySQL触发器和存储过程在我看来很复杂。但是,您可以创建一个过程,并在BEFORE触发器中调用它,传递NEW。job_number,新。Number_from和new。Number_to,然后查询。你的代码将不得不修改,以尝试…捕获你的mysql错误。

您也可以(在PHP中)通过执行一系列这样的查询来实现此目的:

LOCK TABLES jobs WRITE;
SELECT count(*) as countof FROM jobs
WHERE job_number = $job_number
AND (($number_from BETWEEN number_from AND number_to) OR ($number_to BETWEEN number_from AND number_to));
// Fetch the result, and if it's == 0, then you insert.
UNLOCK TABLES;

如果您决定使用带有CALL Procedure(params…)技术的触发器,查询的内部将是相同的,只是您将传递NEW。

UPDATE:根据评论中@benga和@gview的澄清,我已经重写了答案

为了避免重叠,您可以通过触发器或编写应用程序逻辑(在您的情况下是PHP)来实现。在这两种情况下,您都需要作为参数new_number_fromnew_number_to。前者是新表项的number_from值。后者是新表项的number_to值。你还需要new_job_number

下面的查询返回与参数$new_number_from$new_number_to为id为$job_number的作业指定的范围重叠的所有行

SELECT * FROM jobs WHERE 
  job_number=$jobNumber AND 
  number_from <= $new_number_to AND
  number_to >= $new_number_from

如果您使用PHP实现这个,您可以执行这个查询并检查是否返回任何行。如果返回空结果集,则没有冲突。否则会有冲突。

注意:您可能更喜欢获得计数(SELECT COUNT(*))而不是返回行(SELECT *)

我个人觉得这个更有可读性…

$query = "
INSERT INTO jobs 
(user_id
,number_from
,number_to
,client
,cardtype
,job_number
,job_quantity
,status) VALUES 
('$user_id'
,'$number_from'
,'$number_to'
,'$client'
,'$card_type'
,'$job_number'
,'$job_quantity'
,'$status'
);
";

我包含了倒逗号只是因为我不知道你的值是字符串