Oracle 希望我使用 Long 而不是 CLOB

Oracle wants me to use a Long instead of a CLOB

TLDR:Oracle 说我只能绑定一个 LONG 值以插入到一个 LONG 列中...但是该列是一个 CLOB,我相信它应该能够处理这个大小的值。

我有一个带有 CLOB 列的 table:

  CREATE TABLE "WEB"."DATA_EXPLORER_QUERIES" 
   (    "ID" NUMBER NOT NULL ENABLE, 
    "USER_ID" NUMBER NOT NULL ENABLE, 
    "CREATE_DATE" DATE NOT NULL ENABLE, 
    "LAST_RUN" DATE DEFAULT sysdate NOT NULL ENABLE, 
    "RUNS" NUMBER(*,0) DEFAULT 1 NOT NULL ENABLE, 
    "TITLE" VARCHAR2(2500 BYTE) NOT NULL ENABLE, 
    "SLUG" VARCHAR2(2500 BYTE) NOT NULL ENABLE, 
    "SQL" CLOB NOT NULL ENABLE
   ) SEGMENT CREATION IMMEDIATE 
  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 
 NOCOMPRESS NOLOGGING
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "USERS" 
 LOB ("SQL") STORE AS SECUREFILE (
  TABLESPACE "USERS" ENABLE STORAGE IN ROW CHUNK 8192
  NOCACHE NOLOGGING  NOCOMPRESS  KEEP_DUPLICATES 
  STORAGE(INITIAL 106496 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)) ;

我正在尝试通过 PHP:

插入一些数据
$q = $pdo_internal->prepare("insert into data_explorer_queries (id, user_id, create_date, last_run, runs, title, slug, sql) values (?, ?, sysdate, sysdate, 1, ?, ?, ?)");
$q->execute([
    $id,
    $_SESSION['user_id'],
    $_POST['title'],
    $modified_slug,
    $_POST['sql']
]);

这里有一个var_dump的数据:

array (size=5)
  0 => string '5' (length=1)
  1 => string '1078' (length=4)
  2 => string 'test' (length=4)
  3 => string 'test' (length=4)
  4 => string 'select
ziplist.n,
sz.zip,
round((nvl(sz.home_count,0) + nvl(sz.apt_count,0)) * .01515) as census_average
from standard_zip sz
inner join (
select 1 as n, 59421 as zip from dual
union all select 2 as n, 83213 as zip from dual
union all select 3 as n, 59201 as zip from dual
union all select 4 as n, 89001 as zip from dual
union all select 5 as n, 59410 as zip from dual
union all select 6 as n, 83128 as zip from dual
union all select 7 as n, 59937 as zip from dual
union all select 8 as n, 84021 as '... (length=22066)

这将引发以下异常:

PDOException: SQLSTATE[HY000]: General error: 1461 OCIStmtExecute: ORA-01461: can bind a LONG value only for insert into a LONG column

有趣的是,当我打开 SQLDeveloper 并双击 table 中 CLOB 列中的任何值时,我能够粘贴这个长字符串并通过 UI 保存它。显然这只是使用 PHP/PDO.

时的问题

我做错了什么?我该如何解决这个问题?

在我将其标记为重复之前,为了方便起见,我会在这里留下一个答案。 (归功于

Per , PHP Bug #57095 表示在将参数传递给 execute 方法时,插入 CLOB 值无法按预期工作。

解决方法是使用 bindParam 并将 CLOB 类型指定为字符串,并包括第 4 个参数以指示 CLOB 值的字符串大小。

我更新后的工作代码:

$q = $pdo_internal->prepare("insert into data_explorer_queries (id, user_id, create_date, last_run, runs, title, slug, sql) values (?, ?, sysdate, sysdate, 1, ?, ?, ?)");
$q->bindParam(1, $id, PDO::PARAM_INT);
$q->bindParam(2, $_SESSION['user_id'], PDO::PARAM_INT);
$q->bindParam(3, $_POST['title']);
$q->bindParam(4, $modified_slug);
$q->bindParam(5, $_POST['sql'], PDO::PARAM_STR, strlen($_POST['sql']));
$q->execute();