我是oracle sql的新手,pl sql.i有写pl sql函数,它以xml格式从php获取数据。这是下面的pl sql代码,它运行正常:
FUNCTION save_overtime(overtime_data NVARCHAR2 ) RETURN clob IS ret clob;
xmlData XMLType;
v_code NUMBER;
v_errm VARCHAR2(100);
BEGIN
xmlData:=XMLType(overtime_data);
INSERT INTO TBL_OVERTIME SELECT x.* FROM XMLTABLE('/overtime'
PASSING xmlData
COLUMNS OT_EMPID NVARCHAR2(10) PATH 'employee_id',
OT_DATE DATE PATH 'date',
OT_HOUR NUMBER(4,0) PATH 'overtime_hour'
) x;
ret:=to_char(sql%rowcount);
COMMIT;
RETURN '<result><status affectedRow='||ret||'>success</status></result>';
EXCEPTION
WHEN OTHERS THEN
v_code := SQLCODE;
v_errm := SUBSTR(SQLERRM, 1, 100);
DBMS_OUTPUT.PUT_LINE (v_code || ' ' || v_errm);
-- '<result><status>Error</status> <error_message>'|| 'Error Code:' || v_code || ' ' || 'Error Message:' || v_errm ||'</error_message> </result>';
RETURN '<result><status>Error</status> <error_message>'|| 'Error Message:' || v_errm ||'</error_message> </result>';
END save_overtime;
在插入数据时,我注意到oracle表也接受大于其初始大小的数据! 例如,以下列接受大于10的数据。
EMPID NVARCHAR2(10)
如果数据长度为12,则需要前10个字符。但我认为 它应该是无效/错误。因为,否则定义列大小是没有意义的。我知道添加约束。但是为这些小东西添加许多约束是非常无聊和乏味的。如果我做错了/错误,那么请帮助我明白了。谢谢
答案 0 :(得分:3)
插入不允许并静默截断超过列大小的值。 XMLTable columns
子句正在进行截断;其数据类型表示XMLTable投影将返回的内容,并不意味着将根据数据类型大小限制验证指定路径的值。向表中添加约束将没有任何区别。
如果只是从XMLTable表达式查询,而不是插入:
,则可以看到截断var overtime_data nvarchar2(4000);
exec :overtime_data := '<overtime><employee_id>invalidvalue</employee_id><date>2016-01-15</date><overtime_hour>1234.5</overtime_hour></overtime>';
select x.ot_empid, x.ot_date, x.ot_hour
from xmltable('/overtime'
passing xmltype(:overtime_data)
columns ot_empid nvarchar2(10) path 'employee_id',
ot_date date path 'date',
ot_hour number(4,0) path 'overtime_hour'
) x;
OT_EMPID OT_DATE OT_HOUR
---------- --------- ----------
invalidval 15-JAN-16 1235
XML元素的12个字符值被截断以适合columns
子句。还要注意小时数是四舍五入以适应约束数字类型 - 1234.5向上舍入到1235.(只要该值可以转换为指定的精度,它就不会抱怨。基本上这意味着只要在小数点前不要超过四位数它将被舍入;如果在小数点前有五位或更多位数,它将得到一个ORA-01438。)
如果您尝试插入这些值,则不会抱怨,因为它们对表定义有效:
insert into tbl_overtime (ot_empid, ot_date, ot_hour)
select x.ot_empid, x.ot_date, x.ot_hour
from xmltable('/overtime'
passing xmltype(:overtime_data)
columns ot_empid nvarchar2(10) path 'employee_id',
ot_date date path 'date',
ot_hour number(4,0) path 'overtime_hour'
) x;
1 row inserted.
如果您在插入之前不打算验证或操作该值,并且如果XML节点值超过10个字符,您确实希望它出错,那么使XMLTable列数据类型甚至更大的一个字符将起作用。 (如果你要验证值,那么你可以把它做得更大;但是这里的任何东西都会超过10个。)
INSERT INTO TBL_OVERTIME SELECT x.* FROM XMLTABLE('/overtime'
PASSING xmlData
COLUMNS OT_EMPID NVARCHAR2(11) PATH 'employee_id',
OT_DATE DATE PATH 'date',
OT_HOUR NUMBER(4,0) PATH 'overtime_hour'
) x;
如果路径中的值超过10个字符,则x.ot_empid
值将被截断为11个字符,然后插入将失败,因为它对于实际表列而言太大。
使用与以前相同的数据进行演示;
select x.ot_empid, x.ot_date, x.ot_hour
from xmltable('/overtime'
passing xmltype(:overtime_data)
columns ot_empid nvarchar2(11) path 'employee_id',
ot_date date path 'date',
ot_hour number(4,0) path 'overtime_hour'
) x;
OT_EMPID OT_DATE OT_HOUR
----------- --------- ----------
invalidvalu 15-JAN-16 1235
注意ot_empid
列现在有11个字符。现在插入失败:
insert into tbl_overtime (ot_empid, ot_date, ot_hour)
select x.ot_empid, x.ot_date, x.ot_hour
from xmltable('/overtime'
passing xmltype(:overtime_data)
columns ot_empid nvarchar2(11) path 'employee_id',
ot_date date path 'date',
ot_hour number(4,0) path 'overtime_hour'
) x;
Error report -
SQL Error: ORA-12899: value too large for column "SCHEMA"."TBL_OVERTIME"."OT_EMPID" (actual: 11, maximum: 10)