17.6 Properties

属性与字段的区别
本文介绍了在编程中属性的概念,解释了属性如何为对象提供一种访问其内部状态的方式,并且详细对比了属性与字段的不同之处。属性可以指定读取或写入操作时执行的代码,而字段则直接关联于存储位置。
A property is a member that provides access to an attribute of an object or
a class. Examples of properties include
the length of a string, the size of a font, the caption of a window, the
name of a customer, and so on. Properties
are a natural extension of fields?both are named members with associated
types, and the syntax for accessing
fields and properties is the same. However, unlike fields, properties do
not denote storage locations. Instead,
properties have accessors that specify the statements to be executed when
their values are read or written.
Properties thus provide a mechanism for associating actions with the
reading and writing of an object?s attributes;
furthermore, they permit such attributes to be computed.
Properties are declared using property-declarations:
property-declaration:
attributesopt property-modifiersopt type member-name {
accessor-declarations }
property-modifiers:
property-modifier
property-modifiers property-modifier
C# LANGUAGE SPECIFICATION
240
property-modifier:
new
public
protected
internal
private
static
virtual
sealed
override
abstract
extern
member-name:
identifier
interface-type . identifier
A property-declaration may include a set of attributes (§24) and a valid
combination of the four access modifiers
(§17.2.3), the new (§17.2.2), static (§17.6.1), virtual (§17.5.3, §17.6.
3), override (§17.5.4, §17.6.3),
sealed (§17.5.5), abstract (§17.5.6, §17.6.3), and extern modifiers.
Property declarations are subject to the same rules as method declarations (
§17.5) with regard to valid
combinations of modifiers.
The type of a property declaration specifies the type of the property
introduced by the declaration, and the
member-name specifies the name of the property. Unless the property is an
explicit interface member
implementation, the member-name is simply an identifier. For an explicit
interface member implementation
(§20.4.1), the member-name consists of an interface-type followed by a ?.?
and an identifier.
The type of a property must be at least as accessible as the property
itself (§10.5.4).
The accessor-declarations, which must be enclosed in ?{? and ?}? tokens,
declare the accessors (§17.6.2) of the
property. The accessors specify the executable statements associated with
reading and writing the property.
Even though the syntax for accessing a property is the same as that for a
field, a property is not classified as a
variable. Thus, it is not possible to pass a property as a ref or out
argument.
When a property declaration includes an extern modifier, the property is
said to be an external property.
Because an external property declaration provides no actual implementation,
each of its accessor-declarations
consists of a semicolon.
CREATE OR REPLACE PROCEDURE gtht.sp_show_table_create_test01( IN p_table VARCHAR(100), OUT p_cur_result REFCURSOR ) AUTHID DEFINER AS DECLARE v_sql TEXT; v_last_id INTEGER; BEGIN -- 检查表是否存在(忽略大小写) IF NOT EXISTS ( SELECT 1 FROM information_schema.tables WHERE table_schema = 'gtht' AND LOWER(table_name) = LOWER(p_table) ) THEN RAISE EXCEPTION '表 gtht.% 不存在', p_table; END IF; -- 创建带自增 id 的临时表(模拟 SQL Server 的 @table 变量) DROP SEQUENCE IF EXISTS tmp_sql_lines_seq; CREATE TEMP SEQUENCE tmp_sql_lines_seq; DROP TABLE IF EXISTS tmp_sql_lines; CREATE TEMP TABLE tmp_sql_lines ( s TEXT, id INTEGER DEFAULT nextval('tmp_sql_lines_seq') ); -- 插入 CREATE TABLE 开头 v_sql := 'INSERT INTO tmp_sql_lines (s) VALUES (''CREATE TABLE [' || p_table || '] ('')'; EXECUTE v_sql; EXECUTE 'SELECT currval(''tmp_sql_lines_seq'')' INTO v_last_id; -- 获取列注释 DROP TABLE IF EXISTS tmp_columnsproperties; CREATE TEMP TABLE tmp_columnsproperties AS SELECT a.attname::VARCHAR(100) AS column_name, d.description::VARCHAR(1000) AS column_description FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace JOIN pg_attribute a ON a.attrelid = c.oid LEFT JOIN pg_description d ON d.objoid = c.oid AND d.objsubid = a.attnum WHERE c.relname = LOWER(p_table) -- 表名在 pg_class 中是小写 AND n.nspname = 'gtht' AND a.attnum > 0 AND NOT a.attisdropped; -- 插入字段定义(关键修复:显式判断 NULL,而非依赖 COALESCE) v_sql := 'INSERT INTO tmp_sql_lines (s) ' || 'SELECT ' || ''' ['' || col.COLUMN_NAME || ''] '' || col.DATA_TYPE ' || '|| CASE WHEN col.CHARACTER_MAXIMUM_LENGTH IS NOT NULL THEN ''('' || col.CHARACTER_MAXIMUM_LENGTH || '')'' ELSE '''' END ' || '|| '' '' ' || '|| CASE WHEN a.attidentity IN (''a'',''d'') THEN ''GENERATED BY DEFAULT AS IDENTITY '' ELSE '''' END ' || '|| '' '' ' || '|| CASE WHEN col.IS_NULLABLE = ''NO'' THEN ''NOT '' ELSE '''' END ' || '|| ''NULL '' ' || '|| CASE WHEN col.COLUMN_DEFAULT IS NOT NULL THEN ''DEFAULT '' || col.COLUMN_DEFAULT::text ELSE '''' END ' || '|| CASE WHEN cp.column_description IS NOT NULL AND cp.column_description <> '''' THEN '' /**'' || cp.column_description || ''***/, '' ELSE '','' END ' || 'FROM information_schema.COLUMNS col ' || 'LEFT JOIN tmp_columnsproperties cp ON cp.column_name = col.COLUMN_NAME ' || 'LEFT JOIN pg_attribute a ON a.attrelid = c.oid AND a.attname = col.COLUMN_NAME ' || 'JOIN pg_class c ON c.relname = col.TABLE_NAME AND c.relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = ''gtht'') ' || 'WHERE col.TABLE_NAME = ''' || p_table || ''' AND col.TABLE_SCHEMA = ''gtht'' ' || 'ORDER BY col.ORDINAL_POSITION'; EXECUTE v_sql; v_last_id := currval('tmp_sql_lines_seq'); -- 处理主键 IF EXISTS ( SELECT 1 FROM information_schema.TABLE_CONSTRAINTS WHERE LOWER(TABLE_NAME) = LOWER(p_table) AND CONSTRAINT_TYPE = 'PRIMARY KEY' AND TABLE_SCHEMA = 'gtht' ) THEN v_sql := 'INSERT INTO tmp_sql_lines (s) VALUES ('' PRIMARY KEY ('')'; EXECUTE v_sql; v_sql := 'INSERT INTO tmp_sql_lines (s) ' || 'SELECT '' ['' || kcu.COLUMN_NAME || ''],'' ' || 'FROM information_schema.KEY_COLUMN_USAGE kcu ' || 'JOIN information_schema.TABLE_CONSTRAINTS tc ON tc.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME ' || 'WHERE LOWER(kcu.TABLE_NAME) = ''' || LOWER(p_table) || ''' ' || 'AND tc.CONSTRAINT_TYPE = ''PRIMARY KEY'' ' || 'AND kcu.TABLE_SCHEMA = ''gtht'' ' || 'ORDER BY kcu.ORDINAL_POSITION'; EXECUTE v_sql; EXECUTE 'SELECT currval(''tmp_sql_lines_seq'')' INTO v_last_id; -- 更新最后一行 v_sql := 'UPDATE tmp_sql_lines SET s = LEFT(s, LENGTH(s) - 1) WHERE id = ' || v_last_id; EXECUTE v_sql; v_sql := 'INSERT INTO tmp_sql_lines (s) VALUES ('' )'')'; EXECUTE v_sql; ELSE -- 无主键,去除字段定义最后一行的逗号 v_sql := 'UPDATE tmp_sql_lines SET s = LEFT(s, LENGTH(s) - 1) WHERE id = ' || v_last_id; EXECUTE v_sql; END IF; -- 插入结束括号 v_sql := 'INSERT INTO tmp_sql_lines (s) VALUES ('')'')'; EXECUTE v_sql; -- 输出结果,按插入顺序 OPEN p_cur_result FOR EXECUTE 'SELECT s AS CreateTableSQL FROM tmp_sql_lines ORDER BY id'; END; / 上述存储过程调用失败,目前书数据库版本: gaussdb (GaussDB Kernel 505.2.0.SPC0100 build 2450ca36) compiled at 2024-11-02 19:03:53 commit 9980 last mr 20502 release [2025-08-01 09:56:19.948 CST] : [ERROR] 执行失败 错误代码:[0]SQL错误码:[42601] [172.25.101.153:60303/10.187.17.6:8000] NOTICE: Table name received: ah_user_role ERROR: query has no destination for result data, 建议:If you want to discard the results of a SELECT, use PERFORM instead., 在位置:PL/pgSQL function inline_code_block line 7 at SQL statement [ERROR POSITION] Line 1, Offset 0 O $$ [QUERY] DO $$ DECLARE v_cursor REFCURSOR; v_sql_line TEXT; BEGIN -- 调用存储过程,传入游标变量 CALL gtht.sp_show_table_create_test('ah_user_role', v_cursor); -- 循环读取结果 LOOP FETCH v_cursor INTO v_sql_line; EXIT WHEN v_sql_line IS NULL; -- 或 NOT FOUND RAISE NOTICE '%', v_sql_line; END LOOP; CLOSE v_cursor; END $$;
最新发布
08-02
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值