如何声明用户定义的记录类型,以便在我不填充其中一个字段时,该字段将遵循其DataGridComboBoxColumn
?
在我的软件包规范中,我定义了以下记录和表类型:
DisplayMemberPath
在包体中,我的功能与此非常相似:
<DataGridComboBoxColumn x:Name="combo"
Header="Glass"
DataContext="{StaticResource jarTypesViewSource}"
ItemsSource="{Binding}"
SelectedValueBinding="{Binding TypeId}"
SelectedValuePath="TypeId"
DisplayMemberPath="Type"/>
敏锐的眼睛会注意到我没有在DEFAULT
字段中插入任何值;我只填充了5个可用字段中的4个。
当我尝试编译此包时,我从包体中收到以下错误:
PL / SQL:ORA-00913:值太多
如果我从/* set up a custom datatypes that will allow us to pass an array of values into CCD_UI procedures and functions */
TYPE RECORD_OPTION_ATTRIBUTES IS RECORD(
option_name VARCHAR2(200) NOT NULL DEFAULT 'INVALID NAME"', /* default intentionally breaks HTML */
option_value VARCHAR2(200) NOT NULL DEFAULT 'INVALID VALUE"', /* default intentionally breaks HTML */
option_selected_ind NUMBER(1) NOT NULL DEFAULT '0',
option_class VARCHAR2(200) DEFAULT NULL,
option_attributes VARCHAR2(200) DEFAULT NULL
);
TYPE TABLE_OPTION_ATTRIBUTES IS TABLE OF RECORD_OPTION_ATTRIBUTES
INDEX BY BINARY_INTEGER;
声明中删除PROCEDURE populate_user_defined_table()
AS
v_criteria_pairs TABLE_OPTION_ATTRIBUTES;
BEGIN
SELECT some_column1 AS option_name, some_column2 AS option_value, some_column3 AS selected_ind,
some_column4 AS option_class
BULK COLLECT INTO v_criteria_pairs
FROM Some_Table
WHERE some_column='whatever';
END;
字段,则包将编译。
如何声明记录类型,以便在我没有为option_attributes
指定值时,该字段将默认为option_attributes
?
答案 0 :(得分:1)
按照Oracle doc的AFAIK,&#34;要将记录中的所有字段设置为默认值,请为其分配相同类型的未初始化记录&#34;,这是他们的示例:
DECLARE
TYPE RecordTyp IS RECORD (field1 NUMBER,
field2 VARCHAR2(32) DEFAULT 'something');
rec1 RecordTyp;
rec2 RecordTyp;
BEGIN
-- At first, rec1 has the values you assign.
rec1.field1 := 100; rec1.field2 := 'something else';
-- Assigning an empty record to rec1
-- resets fields to their default values.
-- Field1 is NULL and field2 is 'something'
-- due to the DEFAULT clause
rec1 := rec2;
DBMS_OUTPUT.PUT_LINE
('Field1 = ' || NVL(TO_CHAR(rec1.field1),'<NULL>') || ',
field2 = ' || rec1.field2);
END;
/
答案 1 :(得分:1)
使用select [bulk collect] into
语法时无法使用。你在评论中说:
如果这两个陈述都成立,那将是疯狂的:1)用户定义的记录允许您定义默认值,2)您必须填充用户定义记录的每个字段。
第一个陈述是真的;第二个仅在您从查询中分配整个记录时才会出现。
对于RECORD类型的记录变量,除非在定义类型时为其指定不同的初始值,否则每个字段的初始值为NULL。
因此,如果您创建一个记录变量,则设置默认值:
declare
v_rec RECORD_OPTION_ATTRIBUTES;
begin
dbms_output.put_line(v_rec.option_name ||':'|| v_rec.option_value
||':'|| v_rec.option_selected_ind ||':'|| v_rec.option_class
||':'|| v_rec.option_attributes);
end;
/
INVALID NAME":INVALID VALUE":0::
PL/SQL procedure successfully completed.
然后,您可以通过单独设置字段值来覆盖默认值。
如果你select into the record variable那么
对于 select_list 中的每一列,记录变量必须具有相应的类型兼容字段。 select_list 中的列必须与记录字段的顺序相同。
它没有明确说明你在选择列表中的更少的值比记录类型更少,但第二句话意味着;你碰巧在记录的末尾添加了额外的字段,但没有什么能阻止你把它放在开头,这更明显地违反了这一点。没有机制指定选择列表中的哪个列映射到记录中的哪个字段,因此您必须以相同的顺序提供完全相同的相同类型的数字。
查询中的值用于填充记录,始终覆盖默认值。您不能提供字段值。 (即使您的查询将列值评估为null,仍然会覆盖默认值;如果您的查询执行SELECT null AS option_name, ...
,则会收到ORA-06502数字或值错误,因为该字段不为null。因此,使用select into
时,无论是否有bulk collect
,都不适用任何默认设置。
不幸的是,您将使用额外字段添加新记录和表类型(您无法将其传递给期望原始类型的过程,因此可能不实用;您可以添加翻译功能但这只是让事情变得更糟),或者正如@MartinSchapendonk建议的那样,接受命中并修改你现有的代码。
您可能不需要更改只处理集合/记录的任何内容,因为它们不会查看新字段 - 尽管可能您会进行一些修改,或者根本没有任何意义。并且您不需要更改任何直接构造记录的内容,因为它们将获得默认的空值,即使它位于游标循环中(不会提取到记录变量中)。您只需(!)需要使用select into
,select bulk collect into
或fetch into
来更改从SQL查询中填充集合/记录的方式。
答案 2 :(得分:0)
TYPE RECORD_OPTION_ATTRIBUTES IS RECORD(
option_name VARCHAR2(200) NOT NULL DEFAULT 'INVALID NAME"', /* default intentionally breaks HTML */
option_value VARCHAR2(200) NOT NULL DEFAULT 'INVALID VALUE"', /* default intentionally breaks HTML */
option_selected_ind NUMBER(1) NOT NULL DEFAULT '0',
option_class VARCHAR2(200) DEFAULT NULL,
option_attributes VARCHAR2(200) DEFAULT NULL
);
TYPE TABLE_OPTION_ATTRIBUTES IS TABLE OF RECORD_OPTION_ATTRIBUTES
INDEX BY BINARY_INTEGER;
PROCEDURE populate_user_defined_table()
AS
CURSOS cur IS -- cursor selecting values without last column
SELECT some_column1 AS option_name, some_column2 AS option_value,some_column3 AS selected_ind, some_column4 AS option_class
FROM Some_Table
WHERE some_column='whatever';
TYPE t_tmp_arr IS TABLE OF cur%rowtype index by pls_integer;
v_tmp_arr t_tmp_arr;
v_criteria_pairs TABLE_OPTION_ATTRIBUTES;
BEGIN
open cur;
fetch cur bulk collect into v_tmp_arr;
close cur;
for i in 1..v_tmp_arr.count loop
-- it's better to wrap it into a function which accepts one type of record and returns another one
v_criteria_pairs(i).option_name := v_tmp_arr(i).option_name;
v_criteria_pairs(i).option_value := v_tmp_arr(i).option_value;
v_criteria_pairs(i).option_selected_ind := v_tmp_arr(i).option_selected_ind;
v_criteria_pairs(i).option_class := v_tmp_arr(i).option_class;
end loop;
END;
答案 3 :(得分:0)
这是对象类型的另一个选项,它不是PL / SQL记录,但具有相同的行为,还有更多用于在构造函数中使用默认值进行初始化的选项(使用表达式和PL / SQL函数):
使用构造函数定义新类型:
CREATE OR REPLACE TYPE RECORD_OPTION_ATTRIBUTES AS OBJECT(
option_name VARCHAR2(200),
option_value VARCHAR2(200),
option_selected_ind NUMBER(1),
option_class VARCHAR2(200),
option_attributes VARCHAR2(200),
constructor function RECORD_OPTION_ATTRIBUTES(
in_option_name VARCHAR2 DEFAULT 'INVALID NAME"', /* default intentionally breaks HTML */
in_option_value VARCHAR2 DEFAULT 'INVALID VALUE"', /* default intentionally breaks HTML */
in_option_selected_ind NUMBER DEFAULT '0',
in_option_class VARCHAR2 DEFAULT NULL,
in_option_attributes VARCHAR2 DEFAULT NULL
)
return self as result
);
在构造函数中使用默认值并且可以使用复杂的初始化逻辑。请记住,您可以拥有多个构造函数。
create or replace type body RECORD_OPTION_ATTRIBUTES
as
constructor function RECORD_OPTION_ATTRIBUTES(
in_option_name VARCHAR2 DEFAULT 'INVALID NAME"', /* default intentionally breaks HTML */
in_option_value VARCHAR2 DEFAULT 'INVALID VALUE"', /* default intentionally breaks HTML */
in_option_selected_ind NUMBER DEFAULT '0',
in_option_class VARCHAR2 DEFAULT NULL,
in_option_attributes VARCHAR2 DEFAULT NULL
)
return self as result
as
begin
self.option_name := in_option_name;
self.option_value := in_option_value;
self.option_selected_ind := in_option_selected_ind;
self.option_class := in_option_class;
self.option_attributes := in_option_attributes;
return;
end;
end;
/
让我们运行test sql:
select RECORD_OPTION_ATTRIBUTES(table_name, tablespace_name, ini_trans)
from all_tables
where owner = 'SYS'
and rownum <= 10;
检查结果:
RECORD_OPTION_ATTRIBUTES(TABLE_NAME,TABLESPACE_NAME,INI_TRANS)(OPTION_NAME, OPTI
--------------------------------------------------------------------------------
RECORD_OPTION_ATTRIBUTES('WRR$_REPLAY_CALL_FILTER', 'SYSAUX', 1, NULL, NULL)
RECORD_OPTION_ATTRIBUTES('AW$EXPRESS', 'SYSAUX', 4, NULL, NULL)
RECORD_OPTION_ATTRIBUTES('AW$AWMD', 'SYSAUX', 4, NULL, NULL)
RECORD_OPTION_ATTRIBUTES('AW$AWCREATE', 'SYSAUX', 4, NULL, NULL)
RECORD_OPTION_ATTRIBUTES('AW$AWCREATE10G', 'SYSAUX', 4, NULL, NULL)
RECORD_OPTION_ATTRIBUTES('AW$AWXML', 'SYSAUX', 4, NULL, NULL)
RECORD_OPTION_ATTRIBUTES('AW$AWREPORT', 'SYSAUX', 4, NULL, NULL)
RECORD_OPTION_ATTRIBUTES('DUAL', 'SYSTEM', 1, NULL, NULL)
RECORD_OPTION_ATTRIBUTES('SYSTEM_PRIVILEGE_MAP', 'SYSTEM', 1, NULL, NULL)
RECORD_OPTION_ATTRIBUTES('TABLE_PRIVILEGE_MAP', 'SYSTEM', 1, NULL, NULL)
10 rows selected.
正如您所看到的,最后2列具有默认值(在本例中为null)值。 与您的问题中的原始SQL查询相比,您需要做的就是用RECORD_OPTION_ATTRIBUTES()包装选定的列。