Sql-Server

將 SQL Server 查詢轉換為 PostgreSQL

  • December 19, 2020

我正在嘗試使用 CTE 或函式將以下 SQL Server T-SQL 塊轉換為與 PostgreSQL 兼容的塊。轉換的問題是我無法弄清楚如何返回最後插入的 id(scope_identity()在 SQL Server 中返回標識列中最後插入的 id)。

IF (
       NOT EXISTS (
           SELECT p_id
           FROM qr_request
           WHERE q_ota = 'Done'
                           )
       )
BEGIN
   INSERT INTO qr_request (
       u_id
       ,c_id
       ,r_id
       ,q_ota
       )
   VALUES (
       1
       ,2
       ,3
       ,'P'
       )

   COMMIT

   SELECT Scope_Identity() AS id
       ,p.email AS n
   FROM person p
   WHERE p.uid = 33
       AND deleted = 0
       
END
ELSE
   SELECT NULL AS id
       ,p.email AS n
   FROM person p
   WHERE p.uid = 33
       AND deleted = 0

任何幫助,將不勝感激。

由於 PostgreSQL 不像 SQL Server 那樣在表上使用相同的傳統“ID”概念,而是使用序列,因此獲取最後一個值有點不同,但有很多方法可以做到這一點,正如在這個精通StackOverflow 的答案中所注意到的那樣.

具體來說,您可以利用的功能是CURRVAL 和 LASTVAL

來自上述和連結的 StackOverflow 答案的相關資訊:

CURRVAL():

INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John');
 SELECT currval('persons_id_seq');

必須知道序列的名稱。警告: currval() 僅在同一會話中的 INSERT (已執行 nextval() )之後有效。

LASTVAL():

這與前麵類似,只是您不需要指定序列名稱:它會查找最近修改的序列(始終在您的會話中,與上述相同的警告。)

由於 SQL(或 Postgres)中沒有 IF,我將重寫它以使用數據修改公用表表達式

with new_request as (
 INSERT INTO qr_request (u_id,c_id,r_id,q_ota)
 select * 
 from ( VALUES (1,2,3,'P') ) as x(u_id,c_id,r_id,q_ota)
 where not exists (SELECT p_id
                   FROM qr_request
                   WHERE q_ota = 'Done')
 returning id --<< returns the generated ID if an INSERT happened
) 
select nr.id, 
      p.email AS n
FROM person p
 left join new_request nr on true
WHERE p.uid = 33
 AND deleted = 0
;

顯然qr_request.id必須定義為它在插入期間自動生成一個新值。推薦的方法是使用generated always as identity. 所以如果你在 SQL Server 中有這個:

create table qr_request
(
 id   integer identity primary key
 u_id integer, 
 c_id integer, 
 r_id integer, 
 q_ota varchar(5)
);

您將在 Postgres 中使用以下內容:

create table qr_request
(
 id   integer primary key generated always as identity
 u_id integer, 
 c_id integer, 
 r_id integer, 
 q_ota varchar(5)
);

引用自:https://dba.stackexchange.com/questions/281511