利用cursor及fetch将一个表中符合条件的记录拷贝到另一个表中

本文介绍如何使用Oracle的匿名块结合光标技术,实现特定条件下从一个表向另一个表迁移数据的过程。具体而言,通过判断ID是否为5的倍数来决定是否进行数据复制。

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

晚上的时间,都是我自己的,我就好好的利用这个时间来学习学习ORACLE,去年学过的东西都忘得差不多了,现在趁机会还没有忘完之前拿起来。
今天看了一下匿名块、函数、过程等,想起原来用过光标cursor及fetch,也是快忘得差不多了,那今天就来试试把一个表里面的数据拷贝到另外一个结构完全相同的表里面,不过,有一个条件就是原表的ID必须为5的倍数的才能够被插入,否则不取。
在开始之前,还是先来复习一点东西:
1、匿名块的格式基本就如下面所示
[declare]
/*变量定义区,也可做初使化等*/
begin
/*开始区,执行顺序SQL语句*/
[exception]
/*异常处理区,可进行异常处理,异常的抛出使用raise关键字*/
end;
其中方框里面的为可选项,不作为必须。
2、fetch
1)首先要定义cursor,如cursor id_cur is select id from components
2)然后打开cursor:open id_cur
3)第三是使用fetch从cursor并保存到变理中
4)第四关闭cursor
那就把上面说到的功能实现,代码如下:

declare
       num_id integer;/*定义变量*/
       sql_str varchar(1000);
       cursor id_cur is select id from components;/*用光标取ID*/
begin
       open id_cur;/*打开光标执行*/
       loop/*一直执行下去*/
            fetch id_cur into num_id;/*根据光标,取出ID号到变量中*/
            exit when id_cur%notfound;/*没有记录时就退出*/
            if mod(num_id,5)=0 then/*如果记录ID为5的倍数,就执行下面的插入*/
               /*下面生成一条SQL语句*/
               sql_str:='insert into components2 select * from components where id='|| num_id;
               /*立即执行生成的SQL语句*/
               execute immediate sql_str;
            end if;/*记住:条件的结束后都要加结束束‘;’*/
       end loop;
       close id_cur;/*关闭光标*/
end;
/ 
<think>我们面临的需求是:在Element UI的格单元格内嵌入树形组件,并实现从树节点拖拽到其他div的功能,且拖拽的数据只包含当前节点而不包含其子节点。 分析: 1. 在el-table的单元格内使用el-tree组件。 2. 实现拖拽功能:从树节点拖拽到一个div(目标容器)。 3. 拖拽的数据要求:只包含当前节点,不包含其子节点。 实现思路: 1. 使用Element UI的el-table和el-tree组件。 2. 利用el-tree的拖拽功能(通过设置`draggable`属性为true),并自定义节点拖拽事件。 3. 在拖拽开始时(`node-drag-start`事件),我们需要准备要传递的数据,这里我们只需要当前节点(不包括子节点)。 4. 在目标div上监听拖拽事件(dragenter, dragover, drop等),并在drop事件中获取传递的数据。 关键点: - 在el-tree中,默认的拖拽行为会包含整个节点对象(包括children)。我们需要在拖拽开始时,创建一个只包含当前节点(不含children)的数据对象,并将其放入数据传递对象(dataTransfer)中。 - 由于el-tree的节点拖拽是HTML5原生拖拽,我们可以使用`event.dataTransfer`来传递数据。 步骤: 1. 在el-tree上设置`draggable`属性为true,并监听`node-drag-start`事件。 2. 在`node-drag-start`事件处理函数中,我们克隆当前节点数据,然后删除children属性(避免拖拽数据包含子节点),并将处理后的数据以JSON字符串形式存入`dataTransfer`。 3. 在目标div上,监听`dragover`事件(阻止默认行为以允许放置)和`drop`事件(获取数据并处理)。 注意: - 由于我们只需要当前节点(不包含子节点),所以克隆节点后删除children属性。 - 使用JSON序列化和反序列化来传递数据。 代码示例: 模板部分: ```vue <template> <div> <el-table :data="tableData"> <el-table-column prop="name" label="名称"> <template slot-scope="scope"> <!-- 在单元格内放置el-tree --> <el-tree :data="scope.row.children" node-key="id" :props="defaultProps" :draggable="true" @node-drag-start="handleDragStart" ></el-tree> </template> </el-table-column> </el-table> <!-- 目标div --> <div class="drop-area" @dragover.prevent @drop="handleDrop" >拖拽到此处</div> </div> </template> ``` 脚本部分: ```javascript export default { data() { return { tableData: [ { id: 1, name: '节点1', children: [ { id: 2, name: '子节点1' }, { id: 3, name: '子节点2' } ] } // ... 其他数据 ], defaultProps: { children: 'children', label: 'name' } }; }, methods: { handleDragStart(node, event) { // 克隆节点数据,避免修改原节点 const nodeData = { ...node.data }; // 删除children属性,这样传递的数据就不包含子节点 delete nodeData.children; // 将节点数据以JSON字符串形式存入dataTransfer event.dataTransfer.setData('text/plain', JSON.stringify(nodeData)); }, handleDrop(event) { // 从dataTransfer中获取数据 const data = event.dataTransfer.getData('text/plain'); if (data) { try { const nodeData = JSON.parse(data); console.log('拖拽过来的节点数据:', nodeData); // 在这里进行你的业务处理 } catch (e) { console.error('解析拖拽数据失败', e); } } event.preventDefault(); } } }; ``` 样式部分(可选): ```css .drop-area { width: 300px; height: 300px; border: 1px dashed #ccc; text-align: center; line-height: 300px; } ``` 注意事项: 1. 在`handleDragStart`中,我们使用`event.dataTransfer.setData`设置数据,注意MIME类型使用`text/plain`(也可以使用`application/json`,但`text/plain`更通用)。 2. 在目标div的dragover事件上,必须调用`preventDefault()`来允许放置。 3. 在drop事件中,同样需要调用`preventDefault()`来防止浏览器默认行为(如打开文件等)。 这样,我们就实现了从el-table单元格内的el-tree中拖拽单个节点(不包含子节点)到目标div的功能。 相关问题: 1. 如何实现在拖拽过程中自定义拖拽图标? 2. 如何限制某些节点不可拖拽? 3. 如何实现拖拽到目标区域后的视觉反馈?</think>在 Element UI 中实现从 el-table 单元格内的 el-tree 拖拽特定节点(不含子节点)到其他 div 的功能,需要结合自定义拖拽逻辑。以下是完整实现方案: ### 核心实现思路 1. **禁用 el-tree 默认拖拽**:通过 `:draggable="true"` 启用原生拖拽能力 2. **自定义拖拽数据**:在 `@node-drag-start` 事件中准备仅包含当前节点的数据 3. **目标容器处理**:在目标 div 上监听 `dragover` 和 `drop` 事件接收数据 ### 完整代码实现 ```vue <template> <div> <!-- 格区域 --> <el-table :data="tableData" style="width: 100%"> <el-table-column prop="name" label="分类"> <template v-slot="{ row }"> <!-- 单元格内的树形组件 --> <el-tree :data="row.treeData" node-key="id" :props="treeProps" :draggable="true" @node-drag-start="handleDragStart" ></el-tree> </template> </el-table-column> </el-table> <!-- 拖拽目标区域 --> <div class="drop-target" @dragover="handleDragOver" @drop="handleDrop" > 拖拽到此处 (仅接收当前节点) </div> </div> </template> <script> export default { data() { return { tableData: [ { id: 1, name: "类别A", treeData: [ { id: "node1", label: "节点1", children: [ { id: "node1-1", label: "子节点1-1" }, { id: "node1-2", label: "子节点1-2" } ] }, // 更多节点... ] }, // 更多格行... ], treeProps: { label: "label", children: "children" }, // 存储当前拖拽的节点数据 draggingNode: null }; }, methods: { // 拖拽开始事件 handleDragStart(node) { // 创建仅包含当前节点的数据副本 (不含子节点) const nodeData = { ...node.data, children: undefined // 显式移除子节点 }; this.draggingNode = nodeData; // 设置拖拽数据传输 const event = window.event; event.dataTransfer.setData("text/plain", JSON.stringify(nodeData)); }, // 拖拽悬停事件 (必须阻止默认行为) handleDragOver(e) { e.preventDefault(); e.dataTransfer.dropEffect = "copy"; }, // 放置事件处理 handleDrop(e) { e.preventDefault(); if (!this.draggingNode) return; // 获取拖拽数据 const nodeData = this.draggingNode; console.log("接收到节点:", nodeData); // 实际业务处理 (示例显示通知) this.$message.success(`已接收节点: ${nodeData.label}`); // 重置状态 this.draggingNode = null; } } }; </script> <style> /* 目标区域样式 */ .drop-target { margin-top: 20px; height: 200px; border: 2px dashed #409EFF; display: flex; align-items: center; justify-content: center; font-size: 16px; color: #606266; } </style> ``` ### 关键实现说明 1. **数据准备**: ```javascript const nodeData = { ...node.data, children: undefined // 显式移除子节点 }; ``` 使用扩展运算符创建节点数据的浅拷贝,并显式删除 `children` 属性 2. **数据传输**: ```javascript event.dataTransfer.setData("text/plain", JSON.stringify(nodeData)); ``` 通过 HTML5 原生拖拽 API 传递 JSON 格式数据 3. **目标容器事件**: - `@dragover.prevent`:阻止默认行为允许放置 - `@drop.prevent`:处理放置事件并获取数据 ### 注意事项 1. **浏览器兼容性**: - 现代浏览器均支持原生拖拽 API - 如需兼容 IE11,需添加 polyfill 2. **性能优化**: ```vue <el-tree :data="row.treeData" :load="lazyLoad" ... /> ``` 大数据量时建议使用懒加载,避免初始化渲染性能问题 3. **复杂数据结构**: ```javascript // 深拷贝节点并移除子节点 import { cloneDeep } from 'lodash'; const cleanNode = node => { const copy = cloneDeep(node); delete copy.children; return copy; } ``` 当节点包含循环引用时,需使用深拷贝库处理 4. **跨组件拖拽**: 如需跨组件通信,可使用 Vuex 管理拖拽状态: ```javascript // store.js state: { draggingNode: null }, mutations: { setDraggingNode(state, node) { state.draggingNode = node } } ``` ### 相关问题 1. **如何实现拖拽过程中的视觉反馈?** 可通过 CSS 修改拖拽图像: ```css .el-tree-node__content { cursor: grab; } .el-tree-node__content:active { cursor: grabbing; } ``` 2. **如何限制特定节点不可拖拽?** 在 `handleDragStart` 中添加判断: ```javascript handleDragStart(node) { if (node.data.type === 'fixed') { window.event.preventDefault(); return false; } // ...正常处理 } ``` 3. **如何实现拖拽到格外部元素?** 使用相同的拖拽事件处理机制,只需在目标元素添加相同的 `@dragover` 和 `@drop` 监听 4. **如何获取拖拽源信息?** 在节点数据中添加源标识: ```javascript handleDragStart(node) { const nodeData = { ...node.data, sourceTableRow: this.currentRow.id, // 添加源信息 children: undefined } // ... } ``` 5. **如何优化大数量节点的性能?** 建议: - 启用树组件的虚拟滚动:`<el-tree virtual-scrolling>` - 使用懒加载:`:load="fetchData"` - 分页加载格数据
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值