在PB中动态修改数据窗口DW的SQL语句方法注意事项

本文介绍如何在程序运行过程中动态构造SQL语句,包括使用动态SQL语句的格式和步骤,以及通过修改DataWindow对象的SELECT语句实现动态SQL的一种替代方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

数据库应用程序通常进行一项确定的工作,在编写和编译时就可以确定完整的SQL语句,但是在编译时不能确定SQL语句的具体格式和参数时,只能在程序运行过程中构造SQL语句,需要使用动态SQL语句。以Format 4 动态SQL语句为例,使用格式如下:

 

DECLARE Cursor | Procedure

     DYNAMIC CURSOR | PROCEDURE

     FOR DynamicStagingArea ;

 

PREPARE DynamicStagingArea FROM SQLStatement

     {USING TransactionObject} ;

 

DESCRIBE DynamicStagingArea

     INTO DynamicDescriptionArea ;

 

OPEN DYNAMIC Cursor | Procedure

     USING DESCRIPTOR DynamicDescriptionArea} ;

 

EXECUTE DYNAMIC Cursor | Procedure

     USING DESCRIPTOR DynamicDescriptionArea ;

 

FETCH Cursor | Procedure

     USING DESCRIPTOR DynamicDescriptionArea ;

 

CLOSE Cursor | Procedure ;

 

---- 在使用动态SQL语句时,需准备DynamicStagingArea对象(全局对象SQLSA)和DynamicDescriptionArea对象(全局对象SQLDA)。定义游标或过程,读取PREPARE语句中的SQL语句以及语句中说明的参数和类型,执行FETCH语句后,调用相关的函数逐条读取并处理检索结果。

---- 动态SQL语句虽然解能够在程序运行过程中构造SQL语句,但在实际应用中较少使用。若SELECT语句的结果序列一定,可以通过重新指定DataWindow对象的SELECT语句的方法,达到动态修改SQL语句的功能。运用时首先用Describe函数读取DataWindow对象的SELECT语句,用Replace等函数修改出符合要求的SELECT语句,并且可以增加检索条件,再用SetSQLSelect函数为DataWindow控件指定修改后的SELECT语句。

 

---- 程序代码:

 

string sql_string,sql_new

long   start_pos=1

string old_str     //select语句中需要替换的字符串

string new_str    //替换字符串,可以是结构相同的表名

 

dw_1.settransobject(sqlca)

sql_string=dw_1.Describe("DataWindow.Table.Select")

 

// Find the first occurrence of old_str.

start_pos = Pos(sql_string, old_str, start_pos)

 

// Only enter the loop if you find old_str.

DO WHILE start_pos > 0

 

// Replace old_str with new_str.

sql_string = Replace(sql_string, start_pos,  &

Len(old_str), new_str)

 

// Find the next occurrence of old_str.

start_pos = Pos(sql_string, old_str,  &

start_pos+Len(new_str))

LOOP

 

  sql_new=sql_string+" where ……" //增加where字句

  

//判断setsqlselect 函数调用是否成功 ,不成功则返回  

if (dw_1.setsqlselect(sql_new)=-1) then

messagebox("错误","不能修改SQL语句!",Exclamation!)

   return

end if

 

dw_1.settransobject(sqlca)

dw_1.retrieve()

 

 

---- 使用SetSQLSelect有一定的要求和限制,更改后的SELECT语句在结构上必须与原先的语句匹配,在执行SetSQLSelect函数之前必须用SetTrans或SetTransObject函数设置DataWindow控件的内部事务对象。另外, DataWindow对象的数据源必须是一个不带参数的SELECT语句,如果需要使用检索参数,可以在程序代码中修改SQL Select语句。

<think>我们正在处理一个关于PowerBuilder 9的问题:如何配置动态SQL生成的数据窗口使其可编辑。 根据用户的问题,我们需要关注“动态SQL生成的数据窗口”和“使其可编辑”这两个关键点。 首先,我们需要理解动态SQL生成的数据窗口是什么意思。在PowerBuilder中,数据窗口通常与一个数据窗口对象关联,该对象定义了数据源(如SQL SELECT语句)和显示风格。动态SQL通常指在运行时构建SQL语句,而不是在设计时固定。 在PowerBuilder中,动态创建数据窗口对象可以使用SyntaxFromSQL和Create方法。SyntaxFromSQL函数可以根据提供的SQL SELECT语句生成数据窗口对象的源代码,然后使用Create方法基于这个源代码创建数据窗口对象。 但是,用户提到的是“动态SQL生成的数据窗口”,并且希望这个数据窗口是可编辑的。默认情况下,通过SyntaxFromSQL创建的数据窗口对象,如果其数据源是一个单表查询(或者多表查询但满足某些条件),那么它应该是可编辑的。但如果是复杂的查询(如多表连接),则可能需要设置更新属性。 步骤: 1. 使用事务对象的SyntaxFromSQL函数生成数据窗口源代码。 2. 使用Create方法创建数据窗口控件的数据窗口对象。 3. 设置数据窗口控件的事务对象(SetTransObject)。 4. 检索数据(Retrieve)。 5. 确保更新属性正确设置,以便数据窗口可以提交修改数据库。 但是,对于动态创建的数据窗口,特别是多表连接的情况,我们需要显式设置更新属性,告诉PowerBuilder如何更新数据。 引用[3]提到了使用Create方法创建数据窗口对象,并设置数据窗口对象的数据对象名称和事务对象。但这里用户是动态创建,所以数据对象名称可能是动态生成的,或者直接使用源代码创建。 引用[4]提到了一些关于数据窗口显示技巧,但和可编辑性关系不大。 引用[5]提到了在数据窗口控件的属性中指定数据窗口对象,但动态创建时我们通常不指定一个已存在的数据窗口对象,而是用源代码创建。 因此,我们需要: - 生成数据窗口源代码(使用SyntaxFromSQL)。 - 创建数据窗口对象(使用Create)。 - 设置事务对象。 - 检索数据。 - 设置更新属性(如果需要)。 具体步骤: 1. 构建SQL SELECT语句动态构建)。 2. 使用SQLCA(或其它事务对象)的SyntaxFromSQL函数生成数据窗口源代码。 例如:string ls_syntax, ls_sql ls_sql = "SELECT id, name FROM employee" ls_syntax = SQLCA.SyntaxFromSQL(ls_sql, "Style(Type=Form)", ls_err) IF ls_err <> '' THEN // 处理错误 END IF 3. 使用Create方法创建数据窗口对象: 例如:dw_1.Create(ls_syntax, ls_err) IF ls_err <> '' THEN // 处理错误 END IF 4. 设置事务对象:dw_1.SetTransObject(SQLCA) 5. 检索数据dw_1.Retrieve() 此时,如果数据窗口数据源是单表,那么它应该是可编辑的。但如果是多表,我们需要设置更新属性。 如何设置更新属性以使多表连接的数据窗口可编辑? 实际上,PowerBuilder的数据窗口一次只能更新一个表。所以,我们需要: - 指定要更新的表(Table属性)。 - 指定哪些列是主键(Key Columns)。 - 指定哪些列是可更新的(Update Columns)。 - 设置更新条件(Where Clause for Update/Delete)。 我们可以使用Modify函数或直接使用数据窗口画笔函数(但在脚本中)来设置这些属性。 例如,假设我们有一个多表连接的数据窗口,我们想更新其中一个表(比如表A),那么我们可以: dw_1.Modify("DataWindow.Table.UpdateTable = 'A'") // 设置主键列 dw_1.Modify("DataWindow.Table.UpdateKeyInPlace = 'yes'") // 如果需要 // 设置可更新列 dw_1.Modify("col_a.Update = 'yes'") dw_1.Modify("col_b.Update = 'yes'") // 设置主键列 dw_1.Modify("col_id.Key = 'yes'") 另外,也可以使用函数SetUpdateObject和SetUpdate来设置,但使用Modify修改数据窗口对象的属性是常见方法。 但是,更全面的方法是使用数据窗口控件的函数:SetUpdateProperties,但实际上PowerBuilder没有直接提供这样一个函数,所以我们需要分别设置属性。 另一种方法:使用Describe和Modify函数组合来获取和修改数据窗口对象的属性。 注意:在动态创建数据窗口后,我们可以使用Describe获取当前的更新属性,然后根据需要进行修改。 然而,更简单的方式是,在生成数据窗口源代码之前,我们可以通过设置SyntaxFromSQL的第二个参数(presentation string)中的一些选项来指定更新属性,但这通常不够灵活。 因此,通常的做法是创建后修改更新属性。 总结步骤: 1. 动态生成SQL SELECT语句。 2. 使用SyntaxFromSQL生成数据窗口源代码。 3. 使用Create创建数据窗口对象。 4. 设置事务对象并检索数据。 5. 如果数据源涉及多个表,则使用Modify设置更新属性(表、可更新列、主键列等)。 注意:在设置更新属性时,我们只能选择一个表进行更新。如果用户需要更新多个表,则需要通过编程方式在数据窗口的更新前事件(updateStart)中切换更新表,或者使用多个数据窗口。 下面是一个示例代码片段,展示如何动态创建并设置更新属性(以更新其中一个表为例): 假设我们有一个连接两个表(employee和department)的SQL语句,我们想更新employee表。 代码示例: ``` string ls_sql, ls_syntax, ls_err // 假设已经建立数据库连接 ls_sql = "SELECT e.id, e.name, e.dept_id, d.dept_name FROM employee e, department d WHERE e.dept_id = d.id" ls_syntax = SQLCA.SyntaxFromSQL(ls_sql, "Style(Type=Grid)", ls_err) if ls_err <> '' then messagebox("错误", "SyntaxFromSQL错误:"+ls_err) return end if // 创建数据窗口 if dw_1.Create(ls_syntax, ls_err) = 1 then dw_1.SetTransObject(SQLCA) dw_1.Retrieve() else messagebox("错误", "创建数据窗口错误:"+ls_err) return end if // 设置更新属性:只更新employee表 // 首先,设置更新表 dw_1.Modify("DataWindow.Table.UpdateTable = 'employee'") // 设置主键列(假设id是主键) dw_1.Modify("id.Key = 'yes'") // 设置可更新列(注意:必须设置所有需要更新的列) dw_1.Modify("name.Update = 'yes'") dw_1.Modify("dept_id.Update = 'yes'") // 注意:dept_name来自department表,我们不更新它,所以不设置Update='yes' // 另外,我们还需要设置更新条件(Where子句),通常使用主键和可更新列 // 默认情况下,PowerBuilder会使用所有可更新列来生成Where子句,但我们可以修改 // 设置更新条件为只使用键列(这样在更新时只通过主键来定位记录) dw_1.Modify("DataWindow.Table.UpdateWhere = 1") // 1表示只使用键列,2表示键列和可更新列,0表示键列和原始值(所有列) // 现在,数据窗口应该可以更新employee表了 ``` 注意:在更新时,数据窗口会生成更新employee表的SQL语句,而不会更新department表。 另外,用户可能需要在数据窗口中输入数据后,调用Update()函数来提交更改。 但是,上述方法动态创建数据窗口后通过Modify设置更新属性。如果数据窗口的列名有别名,需要特别注意在Modify时使用别名。 最后,用户的问题是关于PowerBuilder 9,上述方法PB9中是适用的。 因此,回答如下:</think>### PowerBuilder 9 动态SQL数据窗口编辑设置方法 在PowerBuilder 9中,要使动态SQL生成的数据窗口可编辑,需通过以下步骤配置: #### 1. **动态创建数据窗口对象** 使用`SyntaxFromSQL()`和`Create()`方法动态生成数据窗口: ```powerbuilder string ls_sql, ls_syntax, ls_err // 构建动态SQL ls_sql = "SELECT id, name, salary FROM employee WHERE dept_id = " + string(il_dept) // 生成数据窗口语法 ls_syntax = SQLCA.SyntaxFromSQL(ls_sql, "Style(Type=Grid)", ls_err) IF ls_err <> "" THEN MessageBox("错误", "SQL语法错误: " + ls_err) RETURN END IF // 创建数据窗口对象 IF dw_1.Create(ls_syntax, ls_err) <> 1 THEN MessageBox("错误", "创建失败: " + ls_err) RETURN END IF ``` [^3] #### 2. **设置更新属性** 关键步骤:通过`Modify()`配置数据窗口的更新能力: ```powerbuilder // 设置可更新表 dw_1.Modify("DataWindow.Table.UpdateTable = 'employee'") // 设置主键列(假设id为主键) dw_1.Modify("id.Key = 'yes'") // 设置可更新列 dw_1.Modify("name.Update = 'yes'") dw_1.Modify("salary.Update = 'yes'") // 设置更新条件(使用主键定位记录) dw_1.Modify("DataWindow.Table.UpdateWhere = 1") // 1=仅用主键 ``` #### 3. **关联事务对象与检索数据** ```powerbuilder dw_1.SetTransObject(SQLCA) // 关联事务对象 dw_1.Retrieve() // 检索数据 ``` #### 4. **启用编辑功能** ```powerbuilder dw_1.Modify("DataWindow.ReadOnly=no") // 确保非只读 ``` #### 5. **提交更新** 用户修改后调用更新: ```powerbuilder IF dw_1.Update() = 1 THEN COMMIT USING SQLCA; ELSE ROLLBACK USING SQLCA; END IF ``` ### 关键配置说明 | **属性** | **作用** | **示例值** | |--------------------------|--------------------------------------|------------------| | `Table.UpdateTable` | 指定更新的数据库表名 | `'employee'` | | `ColumnName.Key` | 设置主键列 | `id.Key='yes'` | | `ColumnName.Update` | 设置可更新列 | `name.Update='yes'` | | `Table.UpdateWhere` | 更新条件生成策略 | `1`(仅主键) | | `DataWindow.ReadOnly` | 禁用/启用编辑 | `no` | ### 注意事项 1. **多表连接处理** 若SQL涉及多表连接,需指定单一更新表并设置关联列的更新属性: ```powerbuilder dw_1.Modify("dept_id.Update = 'yes'") // 关联字段需可更新 dw_1.Modify("DataWindow.Table.UpdateTable = 'employee'") ``` 2. **数据窗口风格** 在`SyntaxFromSQL()`中推荐使用`Grid`或`Tabular`风格以支持编辑(避免`Crosstab`等只读风格)[^1]。 3. **事务对象一致性** 动态创建的数据窗口必须通过`SetTransObject()`绑定与SQLCA相同的事务对象[^2]。 4. **错误处理** 每次`Modify()`后应检查返回值: ```powerbuilder IF dw_1.Modify(...) = "-1" THEN MessageBox("配置错误", "属性设置失败") END IF ``` 通过以上配置,动态SQL生成的数据窗口即可支持用户编辑和数据库更新。实际应用中需根据SQL结构调整更新属性和主键设置[^4][^5]。 --- ### 相关问题 1. 如何为动态数据窗口添加数据验证规则? 2. 动态SQL数据窗口在更新多表时有哪些限制? 3. PowerBuilder中如何实现动态数据窗口的增量检索? 4. 数据窗口更新失败时如何获取详细的错误信息? [^1]: 在PowerBuilder中,数据窗口控件是创建复杂界面的强大工具。创建日历组件时,可采用以下技巧来增强数据窗口控件的可用性和功能性。 [^2]: 如果应用程序只访问一个数据库,那么使用PowerBuilder的缺省事务对象SQLCA也就可以了。SQLCA是个全局对象,在应用程序的任何地方都可以访问。 [^3]: 使用Create方法创建一个新的数据窗口对象,并设置其属性。 [^4]: 用Line建立漂亮的Grid DataWindow的技巧。 [^5]: 在“General”选项卡中,“DataWindow Object Name”编辑框用于指定与数据窗口控件相关联的数据窗口对象。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值