Php PostgreSQL:唯一冲突:7错误:重复键值违反唯一约束;用户“pkey”;

Php PostgreSQL:唯一冲突:7错误:重复键值违反唯一约束;用户“pkey”;,php,mysql,postgresql,laravel,laravel-5,Php,Mysql,Postgresql,Laravel,Laravel 5,我正在我的Laravel应用程序中使用psql。 我正在尝试创建我的用户,并且不断出现此错误 唯一冲突:7错误:重复键值违反唯一约束“users\u pkey” 这里是我为存储我的用户所做的 下面是我如何创建users表的 我做了我想做的事吗 当我用MySQL钩住我的应用程序时,我现在所拥有的一切都会起作用 任何提示/建议对我都很重要 截图 Postgres处理自动递增的方式与MySQL略有不同。在Postgres中,当您创建serial字段时,您还创建了一个序列字段,用于跟踪要使用的id

我正在我的Laravel应用程序中使用psql。 我正在尝试创建我的用户,并且不断出现此错误

唯一冲突:7错误:重复键值违反唯一约束“users\u pkey”


这里是我为存储我的用户所做的
下面是我如何创建users表的 我做了我想做的事吗

当我用
MySQL
钩住我的应用程序时,我现在所拥有的一切都会起作用

任何提示/建议对我都很重要


截图
Postgres处理自动递增的方式与MySQL略有不同。在Postgres中,当您创建
serial
字段时,您还创建了一个序列字段,用于跟踪要使用的id。此序列字段将以值1开始

在表中插入新记录时,如果未指定
id
字段,它将使用序列值,然后递增序列。但是,如果确实指定了
id
字段,则不会使用序列,也不会更新序列

我假设,当您转到Postgres时,您会播种或导入一些现有用户及其现有ID。当您使用这些用户记录的ID创建这些用户记录时,该序列未被使用,因此它从未被更新

因此,例如,如果您导入了10个用户,您的用户ID为1-10,但您的序列仍然为1。当您尝试在不指定id的情况下创建新用户时,它会从序列(1)中提取值,并且您会得到一个唯一的冲突,因为您已经有一个id为1的用户

要解决此问题,您需要将
users\u id\u seq
序列值设置为现有用户的最大(id)。您可以阅读有关重置序列的更多信息,但也可以尝试类似(未测试)的操作:



仅供参考,这在MySQL中不是问题,因为当手动将值插入到自动递增字段中时,MySQL会自动将自动递增序列更新为最大列值。

以下代码提供了一种在Laravel中执行此操作的方法,而Laravel正是OP所使用的

//从数据库中获取所有表
$tables=\DB::select('select table\u name FROM information\u schema.tables WHERE table\u schema=\'public\'ORDER BY table\u name;');
//在数据库中设置要忽略的表
$ignores=array('admin_setting'、'model_拥有_权限'、'model_拥有_角色'、'password_resets'、'role_拥有_权限'、'sessions');
//循环浏览表格
foreach($tables作为$table){
//如果不忽略该表,则:
如果(!in_数组($table->table_name,$ignores)){
//从该表中获取最大id并向其中添加1
$seq=\DB::table($table->table_name)->max('id')+1;
//将序列更改为现在使用上面的新序列索引重新启动
\DB::select('ALTER SEQUENCE'.$table->table_name'.\u id_seq用'.$seq'重新启动);
}
}

注意-使用ALTER SEQUENCE“阻止并发事务”。如果不需要的话,可以考虑从上面提供的替代解决方案中使用SQL语句。

您的插入中没有UsSersPpKy,并且很可能没有使它在DB中成为自动递增值,因此它得到默认值,该值恰好已经存在于表中的其他地方,导致您的错误。这一定是psql和mysql之间的差异。如何将/user my
id
设置为我的pkey?有可能吗?你100%正确,在我手动提供id后,现在它工作得非常好。很好的解释,不幸的是,代码几乎对我有效-它将指针设置为最后一个插入的元素,但不是最后一个插入的元素之后的下一个,因此它仍然不起作用,因为PostgreSQL尝试使用最后使用的id添加新行-因此可能会出现
max(id)+1
,但在测试这个建议之前,我使用了另一个在别处找到的对我有效的解决方案:
selectsetval('users_id_seq'),(从“users”中选择MAX(id))+1
中添加了max id。当
setval()
的第三个参数为false时,下一次调用序列将返回由
setval()
设置的值。如果将第三个参数更改为
true
,或将其删除,则对序列的下一次调用将返回由
setval()
设置的值之后的值。由于我们在没有行的情况下确保默认值为1,我们希望下一次调用序列返回传递到
setval()
,因此我们需要传递
max(id)+1
,第三个参数为
false
。这是一个非常好的答案,我正是这么做的。从mySQL迁移到Postgres。我对后者赞不绝口,但这个特性/错误不仅仅是一个麻烦。如果我有并发连接,则所有连接都会递增memberId字段,这意味着我必须锁定数据库,获取下一个val并使用该val。我觉得这违背了自动递增/序列号的全部目的。实际上这很糟糕。只提供普通代码不是一个好主意,因为很难理解为什么这个代码应该是问题的解决方案。请详细解释你的答案将如何解决这个问题。@codedge我编辑了答案并提供了每行注释的上下文。对于OP正在使用的工具,即Laravel(PHP),答案似乎是好的。我希望这能像帮助我一样帮助别人。
$user = User::where('account_id','=',$id)->first();
$user->email = $account->email_address;
$user->fb_email = '';
$user->tw_email = '';
$user->fb_access_token = '';
$user->fb_profile_id = '';
$user->fb_page_id = '';
$user->fb_username = '';
$user->save();
CREATE TABLE "users" (
    "id" serial NOT NULL ,
    "account_id" varchar(255) NOT NULL ,
    "email" varchar(255) NOT NULL ,
    "fb_email" varchar(255) NOT NULL ,
    "tw_email" varchar(255) NOT NULL ,
    "created_at" timestamp(0) without time zone,
    "updated_at" timestamp(0) without time zone,
    "fb_access_token" varchar(255) NOT NULL ,
    "fb_profile_id" varchar(255) NOT NULL ,
    "fb_page_id" varchar(255) NOT NULL ,
    "fb_username" varchar(255) NOT NULL ,
    PRIMARY KEY ("id")

);
SELECT setval(pg_get_serial_sequence('users', 'id'), coalesce(max(id)+1, 1), false) FROM users;