如何同时插入两条记录而不重复

时间:2014-01-17 18:35:46

标签: php sql sql-server

我在php和sql server 2005中有一个系统,我创建了一个具有相关数字的表单,我用php ej增加了这个数字。 $ i ++但是当两个人同时按下按钮保存这个表格时,它在数据库中创建了两个相同数字的表格,这是我的代码:

$correlativo=$correlativo+1;
$queryVeri="SELECT * FROM FacturaCabecera WHERE  NumFactura='$correlativo'";
$respVeri=EjecutarlocalFA($queryVeri);
if(count($respVeri)!=0)
{
    $numeroFactura=$numeroFactura+1;
}

INSERT INTO FacturaCuerpo([num_factura])VALUES('$correlativo');

为了解决这个问题,我试图验证表中是否存在相关数字,如果存在,我再次递增数字并插入表中,这不重复数字但不起作用,¿我能怎么做?我希望你能帮助我。

相关的数字必须每六个月再次从1开始我不知道是否有可能有两个主键自动增量

2 个答案:

答案 0 :(得分:1)

num_factura必须是数据库中的主键,您可以将此字段设为自动增量。如果你这样做,你不再需要$ correlativo了。

你必须有这样的东西:

if(count($raspVeri != 0)) insert();
//insert into FacturaCuerpo ("desc", "qty", "whatever") values ($desc, $qty, $whatever);

让MySql处理“numFactura”。另一个建议,尝试使用PDO。祝你好运!

答案 1 :(得分:1)

从Instagram的工程页面中提取,了解他们如何处理主键:

http://instagram-engineering.tumblr.com/post/10853187575/sharding-ids-at-instagram


现有解决方案

存在ID生成问题的许多现有解决方案;以下是我们考虑的一些问题:

在网络应用程序中生成ID

这种方法使ID生成完全取决于您的应用程序,而不是数据库。例如,MongoDB的ObjectId,长度为12个字节,并将时间戳编码为第一个组件。另一种流行的方法是使用UUID

优点:

  1. 每个应用程序线程独立生成ID,最大限度地减少故障点和ID生成争用

  2. 如果您使用时间戳作为ID的第一个组件,则ID仍可按时间排序

  3. 缺点:

    1. 通常需要更多存储空间(96位或更高)才能做出合理的唯一性保证
    2. 某些UUID类型是完全随机的,没有自然排序
    3. 通过专门服务生成ID

      Ex:Twitter的Snowflake,一种Thrift服务,它使用Apache ZooKeeper协调节点,然后生成64位唯一ID

      优点:

      1. Snowflake ID为64位,是UUID的一半
      2. 可以将时间用作第一个组件并保持可排序
      3. 可以在死亡的节点中幸存的分布式系统
      4. 缺点:

        1. 会在我们的架构中引入额外的复杂性和更多“移动部件”(ZooKeeper,Snowflake服务器)
        2. 数据库故障单服务器

          使用数据库的自动递增功能来强制执行唯一性。 Flickr使用这种方法,但有两个票据DB(一个在奇数上,另一个在偶数上)以避免单点故障。

          优点:

          1. DBs很容易理解并具有相当可预测的缩放因子
          2. 缺点:

            1. 最终可能成为写作瓶颈(尽管Flickr报道说,即使规模很大,也不是问题)。
            2. 管理员的另外几台机器(或EC2实例)
            3. 如果使用单个DB,则成为单点故障。如果使用多个DB,则无法再保证它们可以随时间排序。
            4. 在上述所有方法中,Twitter的Snowflake最接近,但运行ID服务所需的额外复杂性是反对它的一点。相反,我们采用了概念上类似的方法,但将其引入PostgreSQL。

              我们的解决方案

              我们的分片系统由数千个“逻辑”分片组成,这些分片在代码中映射到更少的物理分片。使用这种方法,我们可以从几个数据库服务器开始,最终转移到更多,只需将一组逻辑分片从一个数据库移动到另一个数据库,而无需重新打包任何数据。我们使用Postgres的模式功能使脚本和管理变得容易。

              模式(不要与单个表的SQL模式混淆)是Postgres中的逻辑分组功能。每个Postgres DB都可以有多个模式,每个模式可以包含一个或多个表。表名只能是每个模式唯一,而不是每个数据库,默认情况下,Postgres会将所有内容放在名为“public”的模式中。

              每个'逻辑'分片都是我们系统中的Postgres模式,每个模式中都存在每个分片表(例如,喜欢我们的照片)。

              我们通过使用PL / PGSQL,Postgres的内部编程语言和Postgres现有的自动增量功能,将ID创建委托给每个分片内的每个表。

              我们的每个ID都包含:

              • 41比特的时间(以毫秒为单位)(给我们41年的自定义纪元ID)
              • 表示逻辑分片ID的13位
              • 10位代表自动递增序列,模数1024.这意味着我们可以生成1024个ID,每个分片,每毫秒

              让我们来看一个例子:让我们说它是2011年9月9日,下午5点,我们的'纪元'从2011年1月1日开始。自我们的纪元开始以来有1387263000毫秒,所以开始我们的ID ,我们用左移填充最左边的41位:

              id = 1387263000 << (64-41)
              

              接下来,我们为我们尝试插入的特定数据获取分片ID。假设我们按用户ID进行分片,并且有2000个逻辑分片;如果我们的用户ID是31341,则分片ID为31341 % 2000 -> 1341。我们用这个值填充接下来的13位:

              id |= 1341 << (64-41-13)
              

              最后,我们采用自动递增序列的下一个值(此序列对每个模式中的每个表都是唯一的)并填写剩余的位。假设我们已经为这个表生成了5,000个ID;我们的下一个值是5,001,我们采用1024和mod(因此它适合10位)并包含它:

              id |= (5001 % 1024)
              

              我们现在拥有了ID,我们可以使用RETURNING关键字作为INSERT的一部分返回应用服务器。

              这是实现所有这些的PL / PGSQL(对于示例模式安装):

              CREATE OR REPLACE FUNCTION insta5.next_id(OUT result bigint) AS $$
              DECLARE
                  our_epoch bigint := 1314220021721;
                  seq_id bigint;
                  now_millis bigint;
                  shard_id int := 5;
              BEGIN
                  SELECT nextval('insta5.table_id_seq') %% 1024 INTO seq_id;
              
                  SELECT FLOOR(EXTRACT(EPOCH FROM clock_timestamp()) * 1000) INTO now_millis;
                  result := (now_millis - our_epoch) << 23;
                  result := result | (shard_id << 10);
                  result := result | (seq_id);
              END;
              $$ LANGUAGE PLPGSQL;
              

              创建表时,我们会这样做:

              CREATE TABLE insta5.our_table (
                  "id" bigint NOT NULL DEFAULT insta5.next_id(),
                  ...rest of table schema...
              )
              

              就是这样!在我们的应用程序中唯一的主键(作为奖励,在其中包含分片ID以便于映射)。