跳至主要内容

PostgreSQL

PostgreSQL 数据源连接器将 Prisma ORM 连接到 PostgreSQL 数据库服务器。

默认情况下,PostgreSQL 连接器包含一个负责连接到数据库的数据库驱动程序。您可以使用 驱动程序适配器 (预览) 通过 Prisma Client 中的 JavaScript 数据库驱动程序连接到您的数据库。

示例

要连接到 PostgreSQL 数据库服务器,您需要在 Prisma 模式 中配置一个 datasource 块。

schema.prisma
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}

传递给 datasource 块的字段为

  • provider:指定 postgresql 数据源连接器。
  • url:指定 PostgreSQL 数据库服务器的 连接 URL。在本例中,使用 环境变量 提供连接 URL。

使用 node-postgres 驱动程序

v5.4.0 开始,您可以将 Prisma ORM 与 JavaScript 生态系统中的数据库驱动程序一起使用(而不是使用 Prisma ORM 的内置驱动程序)。您可以通过使用 驱动程序适配器 来实现。

对于 PostgreSQL,node-postgres (pg) 是 JavaScript 生态系统中最流行的驱动程序之一。它可以与通过 TCP 访问的任何 PostgreSQL 数据库一起使用。

本节说明如何将其与 Prisma ORM 和 @prisma/adapter-pg 驱动程序适配器一起使用。

1. 启用 driverAdapters 预览功能标志

由于驱动程序适配器目前处于 预览 状态,因此您需要在 Prisma 模式中的 datasource 块上启用其功能标志。

// schema.prisma
generator client {
provider = "prisma-client-js"
previewFeatures = ["driverAdapters"]
}

datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}

将功能标志添加到模式后,重新生成 Prisma Client。

npx prisma generate

2. 安装依赖项

接下来,安装 pg 包和 Prisma ORM 的驱动程序适配器。

npm install pg
npm install @prisma/adapter-pg

3. 使用驱动程序适配器实例化 Prisma Client

最后,当您实例化 Prisma Client 时,需要将 Prisma ORM 的驱动程序适配器的实例传递给 PrismaClient 构造函数。

import { Pool } from 'pg'
import { PrismaPg } from '@prisma/adapter-pg'
import { PrismaClient } from '@prisma/client'

const connectionString = `${process.env.DATABASE_URL}`

const pool = new Pool({ connectionString })
const adapter = new PrismaPg(pool)
const prisma = new PrismaClient({ adapter })

请注意,此代码需要将 DATABASE_URL 环境变量设置为您的 PostgreSQL 连接字符串。您可以在下面了解有关连接字符串的更多信息。

注释

指定 PostgreSQL 模式

您可以通过在实例化 PrismaPg 时传入 schema 选项来指定 PostgreSQL 模式

const adapter = new PrismaPg(pool, {
schema: 'myPostgresSchema'
})

连接详细信息

连接 URL

Prisma ORM 遵循 PostgreSQL 官方指南 中指定的连接 URL 格式,但不支持所有参数,并且包含其他参数,例如 schema。以下是 PostgreSQL 连接 URL 所需组件的概述。

Structure of the PostgreSQL connection URL

基本 URL 和路径

以下是用大写字母表示的占位符值的基本 URL路径结构示例。

postgresql://USER:PASSWORD@HOST:PORT/DATABASE

以下组件构成数据库的基本 URL,它们始终是必需的。

名称占位符描述
主机HOST数据库服务器的 IP 地址/域名,例如 localhost
端口PORT数据库服务器正在运行的端口,例如 5432
用户USER您的数据库用户的名称,例如 janedoe
密码PASSWORD您的数据库用户的密码。
数据库DATABASE您要使用的 数据库 的名称,例如 mydb

参数

连接 URL 也可以使用参数。以下是上面同一个示例,其中三个参数 使用大写字母表示的占位符值。

postgresql://USER:PASSWORD@HOST:PORT/DATABASE?KEY1=VALUE&KEY2=VALUE&KEY3=VALUE

可以使用以下参数。

参数名称必需默认值描述
schemapublic您要使用的 模式 的名称,例如 myschema
connection_limitnum_cpus * 2 + 1连接池 的最大大小。
connect_timeout5等待打开新连接的最长时间(以秒为单位),0 表示没有超时。
pool_timeout10等待从池中获取新连接的最长时间(以秒为单位),0 表示没有超时。
sslmodeprefer配置是否使用 TLS。可能的值:preferdisablerequire
sslcert服务器证书的路径。证书路径相对于 ./prisma 文件夹 解析。
sslrootcert根证书的路径。证书路径相对于 ./prisma 文件夹 解析。
sslidentityPKCS12 证书的路径。
sslpassword用于保护 PKCS12 文件的密码。
sslacceptaccept_invalid_certs配置是否检查证书中缺少的值。可能的值:accept_invalid_certsstrict
host指向包含要用于连接的套接字的目录。
socket_timeout

单个查询终止前等待的最大秒数
pgbouncerfalse配置引擎以启用 PgBouncer 兼容模式
statement_cache_size100自 2.1.0 版起:指定每个连接缓存的预准备语句数量
application_name自 3.3.0 版起:为 application_name 配置参数指定一个值
channel_bindingprefer自 4.8.0 版起:为 channel_binding 配置参数指定一个值
options自 3.8.0 版起:指定在连接开始时发送到服务器的命令行选项

例如,如果您想连接到名为 myschema 的模式,将连接池大小设置为 5 并为查询配置 3 秒的超时。您可以使用以下参数

postgresql://USER:PASSWORD@HOST:PORT/DATABASE?schema=myschema&connection_limit=5&socket_timeout=3

配置 SSL 连接

如果您的数据库服务器使用 SSL,您可以在连接 URL 中添加各种参数。以下是可能参数的概述

  • sslmode=(disable|prefer|require):
    • prefer(默认):如果可能,首选 TLS,接受纯文本连接。
    • disable:不使用 TLS。
    • require:要求 TLS,否则失败。
  • sslcert=<PATH>:服务器证书的路径。这是数据库服务器用于签署客户端证书的根证书。如果证书不存在于系统的受信任证书存储中,则需要提供此证书。对于 Google Cloud,这可能是 server-ca.pem。证书路径是相对于 ./prisma 文件夹 解析的
  • sslidentity=<PATH>:从客户端证书和密钥创建的 PKCS12 证书数据库的路径。这是 PKCS12 格式的 SSL 身份文件,您将使用客户端密钥和客户端证书生成它。它将这两个文件组合在一个文件中,并通过密码保护它们(参见下一个参数)。您可以使用以下命令(使用 openssl)使用您的客户端密钥和客户端证书创建此文件:
    openssl pkcs12 -export -out client-identity.p12 -inkey client-key.pem -in client-cert.pem
  • sslpassword=<PASSWORD>:用于保护 PKCS12 文件的密码。上一步列出的 openssl 命令在创建 PKCS12 文件时会提示输入密码,您需要在此处提供完全相同的密码。
  • sslaccept=(strict|accept_invalid_certs):
    • strict:证书中任何缺少的值都会导致错误。对于 Google Cloud,特别是如果数据库没有域名,证书可能缺少域名/IP 地址,这会导致连接时出错。
    • accept_invalid_certs(默认):绕过此检查。请注意此设置的安全后果。

您的数据库连接 URL 将类似于以下内容

postgresql://USER:PASSWORD@HOST:PORT/DATABASE?sslidentity=client-identity.p12&sslpassword=mypassword&sslcert=rootca.cert

通过套接字连接

要通过套接字连接到您的 PostgreSQL 数据库,您必须将 host 字段作为连接 URL 的查询参数添加(而不是将其设置为 URI 的 host 部分)。然后,此参数的值必须指向包含套接字的目录,例如:postgresql://USER:PASSWORD@localhost/database?host=/var/run/postgresql/

请注意,需要 localhost,其值本身会被忽略,可以是任何内容。

注意:您可以在此GitHub 问题中找到其他上下文。

PostgreSQL 和 Prisma 模式之间的类型映射

这两个表显示了 PostgreSQL 和 Prisma 模式之间的类型映射。首先Prisma ORM 标量类型如何转换为 PostgreSQL 数据库列类型,然后PostgreSQL 数据库列类型如何与 Prisma ORM 标量和原生类型相关联

或者,请参阅Prisma 模式参考,了解按 Prisma 类型组织的类型映射。

Prisma ORM 标量类型和 PostgreSQL 数据库列类型之间的映射

PostgreSQL 连接器将 Prisma ORM数据模型中的标量类型映射到数据库列类型,如下所示

Prisma ORMPostgreSQL
Stringtext
Booleanboolean
Intinteger
BigIntbigint
Floatdouble precision
Decimaldecimal(65,30)
DateTimetimestamp(3)
Jsonjsonb
Bytesbytea

PostgreSQL 数据库列类型到 Prisma ORM 标量和原生类型的映射

PostgreSQL(类型 | 别名)支持Prisma ORM原生数据库类型属性备注
bigint | int8✔️BigInt@db.BigInt**BigInt 的默认映射 - 未向模式添加类型属性。
boolean | bool✔️Bool@db.Boolean**Bool 的默认映射 - 未向模式添加类型属性。
timestamp with time zone | timestamptz✔️DateTime@db.Timestamptz(x)
time without time zone | time✔️DateTime@db.Time(x)
time with time zone | timetz✔️DateTime@db.Timetz(x)
numeric(p,s) | decimal(p,s)✔️Decimal@db.Decimal(x, y)
real | float, float4✔️Float@db.Real
double precision | float8✔️Float@db.DoublePrecision**Float 的默认映射 - 未向模式添加类型属性。
smallint | int2✔️Int@db.SmallInt
integer | int, int4✔️Int@db.Int**Int 的默认映射 - 未向模式添加类型属性。
smallserial | serial2✔️Int@db.SmallInt @default(autoincrement())
serial | serial4✔️Int@db.Int @default(autoincrement())
bigserial | serial8✔️Int@db.BigInt @default(autoincrement()
character(n) | char(n)✔️String@db.Char(x)
character varying(n) | varchar(n)✔️String@db.VarChar(x)
money✔️Decimal@db.Money
text✔️String@db.Text**String 的默认映射 - 未向模式添加类型属性。
timestamp✔️DateTime@db.TimeStamp**DateTime 的默认映射 - 未向模式添加类型属性。
date✔️DateTime@db.Date
enum✔️EnumN/A
inet✔️String@db.Inet
bit(n)✔️String@Bit(x)
bit varying(n)✔️String@VarBit
oid✔️Int@db.Oid
uuid✔️String@db.Uuid
json✔️Json@db.Json
jsonb✔️Json@db.JsonB**Json 的默认映射 - 未向模式添加类型属性。
bytea✔️Bytes@db.ByteA**Bytes 的默认映射 - 未向模式添加类型属性。
xml✔️String@db.Xml
数组类型✔️[]
citext✔️*String@db.Citext* 仅在启用 Citext 扩展时可用。
interval尚未不支持
cidr尚未不支持
macaddr尚未不支持
tsvector尚未不支持
tsquery尚未不支持
int4range尚未不支持
int8range尚未不支持
numrange尚未不支持
tsrange尚未不支持
tstzrange尚未不支持
daterange尚未不支持
point尚未不支持
line尚未不支持
lseg尚未不支持
box尚未不支持
path尚未不支持
polygon尚未不支持
circle尚未不支持
复合类型尚未n/a
域类型尚未n/a

内省添加作为Unsupported字段的尚不支持的原生数据库类型

schema.prisma
model Device {
id Int @id @default(autoincrement())
name String
data Unsupported("circle")
}

预准备语句缓存

一个预准备语句是可以用于优化性能的功能。预准备语句仅解析、编译和优化一次,然后可以多次直接执行,而无需再次解析查询的开销。

通过缓存预准备语句,Prisma Client 的查询引擎不会重复编译相同的查询,从而减少数据库 CPU 使用率和查询延迟。

例如,以下是 Prisma Client 发出的两个不同查询生成的 SQL

SELECT * FROM user WHERE name = "John";
SELECT * FROM user WHERE name = "Brenda";

参数化后的两个查询将相同,第二个查询可以跳过准备步骤,从而节省数据库 CPU 和到数据库的额外往返行程。参数化后的查询

SELECT * FROM user WHERE name = $1

Prisma Client 维持的每个数据库连接都有一个单独的缓存,用于存储预准备语句。可以使用连接字符串中的 statement_cache_size 参数调整此缓存的大小。默认情况下,Prisma Client 每个连接缓存 100 个语句。

由于 pgBouncer 的性质,如果将 pgbouncer 参数设置为 true,则会自动禁用该连接的预准备语句缓存。