如何编写SQL INSERT查询,以避免重复行上某个范围内的数据

时间:2014-05-15 15:26:35

标签: mysql sql

 id | user_id | job_range | start_date | client_name| job_type | job_no     |  job_quan                        
 1  |    4    | 1-3000    | 2014-05-13 |  kenny's   | coloured |   t50000   |    n4500
 2  |    2    | 3001-4500 | 2014-05-13 |  kenny's   | coloured |   t50000   |    n4500
 3  |    3    | 1-2000    | 2014-05-15 |  fredy's   | plain    |   t42100   |    n5000
 4  |    4    |2001-5000  | 2014-05-15 |  fredy's   | plain    |   t42100   |    n5000 

我想编写一个查询,该查询使用已输入数据库(job_range)的数字范围,并将其与job_no匹配,以避免其他用户将作业范围内的作业放入数据库。 数字不能在已经给出的较低范围内。对于任何特定作业,如果范围为1-2000,那么您无法在该作业的表中添加另一行,范围从1-2000开始,只能选择2001到5000之间的作业。所以用户只能选择做工作btw范围2001 -5000

6 个答案:

答案 0 :(得分:2)

您必须制作专栏UNIQUE。您可以通过运行此查询来执行此操作(您需要先删除重复的条目):

ALTER TABLE jobs ADD UNIQUE (desc)

然后,当您尝试运行查询并且desc列已经存在时,它将返回错误。

答案 1 :(得分:1)

CREATE TABLE test_dup (id number, dup_from number,dup_to number);

create table dup_val_range (range_values NUMBER);

 ALTER TABLE dup_val_range
ADD CONSTRAINT rng_unique unique (range_values);

CREATE SEQUENCE rng_seq
INCREMENT BY 1
START WITH 1
MINVALUE 1
MAXVALUE 9999999999999999999
NOCYCLE
NOCACHE
NOORDER;

create or replace procedure ins_rng(p_from IN NUMBER, p_to IN NUMBER)
AS
v_indx1 NUMBER;
BEGIN
IF p_from> p_to THEN

RAISE_APPLICATION_ERROR(-20001, 'from is Higher tham To');

END IF;

-- check for nulls

FOR i IN p_from..p_to
LOOP

    BEGIN
    insert into dup_val_range (range_values)
    values (i);
    EXCEPTION WHEN DUP_VAL_ON_INDEX THEN
    rollback;
    RAISE_APPLICATION_ERROR(-20001, 'Range ir taken!');

    END;

END LOOP;

insert into test_dup
values (rng_seq.nextval,p_from,p_to);

END;


exec ins_rng(p_from=>1, p_to=>19);

exec ins_rng(p_from=>5, p_to=>20);

ORA-20001: Range ir taken!

    select * from dup_val_range 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19


    select * from test_dup
3   1   19

但是,如果不会通过此过程插入值,则会手动添加,这不会有帮助..

答案 2 :(得分:0)

正如Marcell所说,无法在INSERT上使用WHERE。

我倾向于根据你的表格布局和所需的动作在'desc'上设置一个UNIQUE键,然后执行标准的INSERT。如果已经插入了1-300,则INSERT将失败,并且您可以在应用程序中捕获重复键错误。

ALTER TABLE `jobs` ADD UNIQUE (desc);

答案 3 :(得分:0)

如果指定ON DUPLICATE KEY UPDATE,并且插入的行将导致UNIQUE索引或PRIMARY KEY中出现重复值,则执行旧行的UPDATE。例如,如果列a声明为UNIQUE并且包含值1,则以下两个语句具有相同的效果:

INSERT INTO table (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE c=c+1;

UPDATE table SET c=c+1 WHERE a=1;

以下是ON DUPLICATE KEY

的更详细说明和用法

http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html

答案 4 :(得分:0)

你需要一种方法来拆分列(desc到desc_from和desc_to)或(substr string来获取from,to),你需要检查from不能大于to并且可以使用这样的东西.. < / p>

CREATE TABLE test_dup (id number, dup_from number,dup_to number);

select * from test_dup;

 ALTER TABLE test_dup
ADD CONSTRAINT chk_dup CHECK (dup_from<=dup_to);

insert into test_dup
select 1,2,300 from dual where not exists (select 1 from test_dup where 2<=dup_to AND 300>=dup_from);

insert into test_dup
select 2,4,399 from dual where not exists (select 1 from test_dup where 4<=dup_to AND 399>=dup_from);

insert into test_dup
select 3,1,500 from dual where not exists (select 1 from test_dup where 1<=dup_to AND 500>=dup_from);

insert into test_dup
select 4,301,304 from dual where not exists (select 1 from test_dup where 301<=dup_to AND 304>=dup_from);

insert into test_dup
select 4,200,200 from dual where not exists (select 1 from test_dup where 200<=dup_to AND 200>=dup_from);

insert into test_dup
select 4,555,555 from dual where not exists (select 1 from test_dup where 555<=dup_to AND 555>=dup_from);


select * from test_dup;

1   2   300
4   301 304
4   555 555

其他?你可以使用基于函数的约束来进行相同的检查吗? 或者你可以创建一个新的检查表并添加唯一的约束。在插入实际表之前,如果有

,则将所有数据范围放入检查表中,以便在dupval上捕获错误
insert into test_dup
select 1,2,300 from dual where not exists (select 1 from test_dup where 2<=dup_to AND 300>=dup_from AND dup_from<dup_to);
再来一次

create or replace procedure insert_rng (p_id IN NUMBER, p_from IN NUMBER, p_to IN NUMBER)
AS
BEGIN

insert into test_dup
select p_id,p_from,p_to from dual where not exists (select 1 from test_dup where p_from<=dup_to AND p_to>=dup_from AND dup_from<=dup_to);
 IF sql%notfound THEN
RAISE_APPLICATION_ERROR(-20001, 'range taken!');
END IF;

END;

exec insert_rng (p_id=>1, p_from=>1, p_to=>99);

答案 5 :(得分:0)

如果您的INSERT字段中的两个值的某些条件未得到满足,您希望desc失败。

首先,正如user2879235所提到的那样,如果将desc字段拆分为两个单独的列,则会更容易制定条件,让我们称之为startend

另一个问题是desc中值的含义。有时你只有1个值,有时你有2个。 1000只是1000-1000的简写还是别的?我会假设它是。 并100-10001000-1100发生冲突或不发生冲突吗?我会假设他们这样做。

根据这些假设,我认为您的约束可以表述为(请验证这一点!)

NOT EXISTS (
    SELECT j FROM jobs WHERE (j.start <= new.start AND j.end >= new.start)
                          OR (j.start <= new.end AND j.end >= new.end)
)

其中new是新创建的元组。

您希望在尝试插入时检查此约束,但MySQL doesn't support checking CHECK constraints, so you'll need to use a trigger instead可以在满足此约束的相反时提升SIGNAL,这应该回滚(即撤消) INSERT