Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/tfs/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Database 尝试使用随机数据更新列时发生ORA-06502_Database_Oracle_Oracle11g - Fatal编程技术网

Database 尝试使用随机数据更新列时发生ORA-06502

Database 尝试使用随机数据更新列时发生ORA-06502,database,oracle,oracle11g,Database,Oracle,Oracle11g,我试图通过生成一个随机字符串来“清除”表中的一些敏感数据,该字符串的字符数与开始时列中的字符数完全相同。DML如下所示: UPDATE PROD.SUBMISSION SET DATA01 = CAST(dbms_random.string('X', LENGTH(DATA01)) AS VARCHAR2(2000 BYTE)) WHERE DATA01 IS NOT NULL AND LENGTH(DATA01) > 0 当我运行这个程序时,ORA-06502被生成 DATA01列是一

我试图通过生成一个随机字符串来“清除”表中的一些敏感数据,该字符串的字符数与开始时列中的字符数完全相同。DML如下所示:

UPDATE PROD.SUBMISSION
SET DATA01 = CAST(dbms_random.string('X', LENGTH(DATA01)) AS VARCHAR2(2000 BYTE))
WHERE DATA01 IS NOT NULL AND LENGTH(DATA01) > 0
当我运行这个程序时,ORA-06502被生成

DATA01列是一个可为空的VARCHAR2(2000字节)。我看不出有什么问题。该表有100K+行,因此,如果有人能提供有关如何排除故障或深入查找导致问题的记录的建议,那就太好了


关于试图复制问题,我还没有发现任何产生错误的东西

Oracle 11g R2架构设置

CREATE TABLE SUBMISSION (
  DATA01 VARCHAR2(2000)
);

INSERT INTO SUBMISSION VALUES ( 'X' );
INSERT INTO SUBMISSION VALUES ( 'TEST' );
INSERT INTO SUBMISSION VALUES ( NULL );
INSERT INTO SUBMISSION VALUES ( 'Something longer.' );
INSERT INTO SUBMISSION VALUES ( '!"£$%^&*()_+-={}[];:''@~#,<.>/?\|`¬' );
INSERT INTO SUBMISSION VALUES ( DBMS_RANDOM.STRING('X',2000) );

UPDATE SUBMISSION
SET DATA01 = DBMS_RANDOM.STRING('X', LENGTH(DATA01))
WHERE DATA01 IS NOT NULL;
SELECT SUBSTR(DATA01,1,60) FROM SUBMISSION
|                                          SUBSTR(DATA01,1,60) |
|--------------------------------------------------------------|
|                                                            U |
|                                                         WSB8 |
|                                                       (null) |
|                                            QNKHK0FVM8A7BO50H |
|                           V3NF2NJQLL5TLHD4HCW1NWDXZPSBVS0OBH |
| CUZSH86NDMX9QQN4DC1DEVTFRXGKEW3INKAVCNZANL53NMU5OW5FJ5X4SFDW |

CREATE TABLE SUBMISSION (
  DATA01 VARCHAR2(2000)
);

INSERT INTO SUBMISSION VALUES ( 'X' );
INSERT INTO SUBMISSION VALUES ( 'TEST' );
INSERT INTO SUBMISSION VALUES ( NULL );
INSERT INTO SUBMISSION VALUES ( 'Something longer.' );
INSERT INTO SUBMISSION VALUES ( '!"£$%^&*()_+-={}[];:''@~#,<.>/?\|`¬' );
INSERT INTO SUBMISSION VALUES ( DBMS_RANDOM.STRING('X',2000) );

UPDATE SUBMISSION
SET DATA01 = DBMS_RANDOM.STRING('X', LENGTH(DATA01))
WHERE DATA01 IS NOT NULL;
SELECT SUBSTR(DATA01,1,60) FROM SUBMISSION
|                                          SUBSTR(DATA01,1,60) |
|--------------------------------------------------------------|
|                                                            U |
|                                                         WSB8 |
|                                                       (null) |
|                                            QNKHK0FVM8A7BO50H |
|                           V3NF2NJQLL5TLHD4HCW1NWDXZPSBVS0OBH |
| CUZSH86NDMX9QQN4DC1DEVTFRXGKEW3INKAVCNZANL53NMU5OW5FJ5X4SFDW |
编辑

您可以运行以下命令:

UPDATE PROD.SUBMISSION
SET DATA01 = DBMS_RANDOM.STRING('X', LENGTH(DATA01))
WHERE DATA01 IS NOT NULL
AND   ROWID IN ( SELECT ROWID
                 FROM   ( SELECT ROW_NUMBER() OVER ( ORDER BY NULL ) AS RN
                          FROM SUBMISSION )
                 WHERE  RN BETWEEN 1 AND 1000 );

如果在最后一行中改变BEVERY子句中的值,则可以尝试缩小导致问题的行。

我能想到的唯一正确原因是DBMS_RANDOM的length参数引用字符长度,并且生成的字符串可以包括多字节字符。这意味着,如果将长度传递到2000,则可能会返回一个包含2000个字符但超过2000个字节的字符串,而该字符串不适合VARCHAR2(2000字节)列

您可以尝试对DBMS_RANDOM使用不同的第一个参数-也许您会更幸运地使用更受限制的字符集

缩小问题范围的另一个想法是分别为每个可能的长度运行更新,例如:

UPDATE PROD.SUBMISSION
SET DATA01 = dbms_random.string('X', LENGTH(DATA01)
WHERE LENGTH(DATA01) = 1
然后重复2,3,等等


如果我上面的假设是正确的,那么你可能会在较小的长度上成功,然后在接近2000年时更有可能出错。

尝试将错误记录到单独的日志表中

创建表和日志:

19:26:22 (15)HR@sandbox> create table errlog_test (key int primary key, value int not null);

Table created.

Elapsed: 00:00:00.06
19:26:49 (15)HR@sandbox> insert into errlog_test values (1,1);

1 row created.

Elapsed: 00:00:00.03
19:26:56 (15)HR@sandbox> exec dbms_errlog.create_error_log('errlog_test');

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.01
执行以下语句:

19:32:05 (15)HR@sandbox> l
  1  update errlog_test set value = null where key = 1
  2* log errors into err$_errlog_test reject limit unlimited
19:32:06 (15)HR@sandbox> /

0 rows updated.

Elapsed: 00:00:00.04
注意:1行中更新了0行。并使用导致错误的记录检查日志:

19:32:07 (15)HR@sandbox> select key, value, ora_err_mesg$ from err$_errlog_test;

KEY VALUE ORA_ERR_MESG$
--- ----- --------------------------------------------------------------------------------
1         ORA-01407: cannot update ("HR"."ERRLOG_TEST"."VALUE") to NULL


Elapsed: 00:00:00.01

感谢大家的辛勤调查。我不确定问题出在哪里,但我们的DBA在表上运行了统计数据并重新启动了服务器。然后我们删除并重新导入生产数据。我最初发布的DDL工作成功。

由于
DATA01
是VARCHAR2类型,因此
DATA01不为NULL
,并且
LENGTH(DATA01)>0
执行相同的操作。如果
DATA01
属于VARCHAR类型,并且Oracle实际上实现了该类型,而不是使用VARCHAR2的别名,那么这些语句将做不同的事情。我不确定我是否看到了
cast
的目的。正如@MT0所指出的,
data01的
WHERE
子句不是空的
对于查询来说就足够了。非NULL
varchar2
的长度不能为0。我已删除长度检查和强制转换,错误仍然发生。感谢您的回复,我很感激。您可以运行
SELECT*FROM v$NLS_参数,其中的参数类似于'NLS_%CHARACTERSET'
并发回您正在使用的字符集?@MT0:NLS_CHARACTERSET=WE8ISO8859P1 NLS_NCHAR_CHARACTERSET=al16utf16在建议的更新上缩小问题范围-您使用同一字段来确定更新正在修改的行号-因此行号将从一次执行更改为下一次执行,而且也不能保证你不会一直更新同一组1000行。好吧,那基本上每次都会对行进行随机排序,不是吗?关于该表,您没有足够的信息,但最好用其他列的范围来划分行,例如主键。@DaveCosta如果有其他键,则可以使用该键;然而,在我所有的测试中,
ROW_NUMBER()OVER(ORDER BY NULL)
似乎以插入顺序返回行数-情况可能并非总是如此,但我从未找到反例来证明这种假设是错误的。返回大写字母数字字符,因此这些字符不应为多字节字符。我同意在最常用的字符集中,这些字符应为单字节。但是字符集确实存在于多字节(例如UTF16)的地方,正如我所说的,这是我能想到为什么会发生错误的唯一原因。即使字符集是UTF-16或UTF-32,
DBMS\u RANDOM生成的字符。STRING('X',len)
都将是1字节字符(由于
X
选项生成大写字母数字字符,而不是补充平面中的代码点),因此随机字符串的长度将小于或(最坏情况下)等于更新前的数据长度。它所占用的字节数不能超过要替换的字符串。