您现在所在的是:

工控软件

回帖:1个,阅读:302 [上一页] [1] [下一页]
9224
紫金桥软件
文章数:2040
年度积分:50
历史总积分:9224
注册时间:2006/1/6
发站内信
发表于:2012/1/10 17:02:46
#0楼
我们都知道,在紫金桥软件中可以通过脚本或报表来访问关系库系统。我们通常的访问方式大概如下(以报表访问关系库为例):

建立报表关系数据源点,配置关系数据源点连接的数据库用户名和密码等属性。
绘制报表,在报表的关系数据库连接中指明第一步建立的报表关系数据源点。
在报表上写对关系库操作的命令,比如SELECT命令。
在报表中对关系库返回的结果进行处理,最简单的是报表自动显示结果。
这里第3步的SELECT命令中可以访问SQL中的表或视图。另外也可以使用存储过程,比如:

#R.SqlExeCmdNoRet("EXEC DOTRANCDATA");

这里的EXEC DOTRANCDATA表示执行DOTRANCDATA这个存储过程。

下面我们通过一个简单的例子来说明一下存储过程的用法。

比如我们需要做一个产品出入库的项目,产品在某一个地方通过驱动或条码设备自动进行入库操作,当数据进入关系库之后,可以通过关系库的各种统计分析查询功能来对产品进行统计和检索,由于需要在多个地方进行检索,所以SQL数据库放在远端网络的一个服务器上。

但是这里存在这么一个问题,由于网络有可能会偶尔出现故障,虽然在故障情况下暂时不能查询是可以理解的,但是我们不能允许在网络出现故障的情况下,产品不能入库。

这种问题可以这么解决,在本地关系库中建立一个缓冲表,数据先插入本地的缓冲表中,然后通过存储过程,把本地的缓冲表中的数据移动到远端的产品库中。在本地的任何检索和查询都是针对的远端的产品库来进行。这样当网络中断的时候,数据就可以先缓冲到本地,此时产品的入库工作仍然可以顺利的进行,只不过本地的数据无法自动的移动到远端,此时在远端的数据库中是无法检索到这些入库的产品的。当网络恢复之后,由存储过程自动的把数据移动到远端数据库中,此时在远端数据库中就可以检索到这些产品了。

下面我们举一个简单的例子,为了简化说明我们的两个表都在本地数据库中,首先数据插入其中的一个表中,然后在使用存储过程移动到另外一个表。对于跨数据库的表,处理方式一样,只需要稍微做些调整就行了。

首先我们在SQL中建立两个表,名为“测试数据源”和“测试目标”,如下图所示:

附件

在测试数据源和测试目标中建立结构相同的两个数据表,如下图所示:

附件

这里是一个简单的人员入库表,表明为User,有三个字段,第一个是自动增长的ID,第二个是人名,第三个年龄。

我们在紫金桥中创建一个关系数据源点,让该点连接“测试数据源”数据库,如下图所示:

附件

在紫金桥中创建一个窗口,并且创建一个报表,给报表关联刚刚建立的报表关系数据源点。

在报表上允许用户输入姓名和年龄,如下图所示:

附件

给姓名和年龄的输入位置设置相应的输入方式,给提交按钮关联如下的脚本:

SqlExeCmdNoRet("INSERT INTO [User](Name, [Year]) VALUES ('"+Txt(1,1)+"', "+Txt(2,1)+")");

即可把人员姓名和年龄插入数据库中。

下面我们通过存储过程来把数据从“测试数据源”库移动到“测试目标”库中。

在“测试数据源”库中创建一个存储过程,如下图所示:

附件

点击确定即可创建存储过程。

打开SQL查询分析器,选中相应的存储过程,右键菜单选择编辑功能,如下图所示:

附件

在此处输入如下的代码:

SET QUOTED_IDENTIFIER ON

GO

SET ANSI_NULLS OFF

GO

ALTERPROCEDURE MoveDataAS



DECLARE @strVARCHAR(1000)

DECLARE @SqlstrVARCHAR(1000)

SET @str = ''

SELECT @str=@str+','+syscolumns.[name] FROM syscolumns WHERE syscolumns.id=object_id('User') and syscolumns.[name]<>'ID'

SET @str = stuff(@str,1,1,'')

SET @str = 'INSERT INTO 测试目标.dbo.[User](' + @str + ') SELECT ' + @str + ' FROM 测试数据源.dbo.[User]'



DECLARE Ptr CURSOR

FOR

SELECT ID FROM 测试数据源.dbo.[User]

OPEN Ptr

DECLARE @ID INT



FETCH NEXT FROM Ptr INTO @ID

WHILE (@@FETCH_STATUS <> -1)

BEGIN

IF (@@FETCH_STATUS <> -2)

BEGIN

SET @Sqlstr = @str + ' WHERE ID=' + CONVERT(varchar, @ID)

EXEC(@Sqlstr)

DELETE FROM 测试数据源.dbo.[User] WHERE ID = @ID

END

FETCH NEXT FROM Ptr INTO @ID

END

CLOSE Ptr

DEALLOCATE Ptr



GO

SET QUOTED_IDENTIFIER OFF

GO

SET ANSI_NULLS ON

GO

其中前面和后面5行代码,是固定的,功能主要是更改存储过程的内容。

中间的内容是移动数据,这里我们不能简单的这样写:

INSERT INTO 测试目标.dbo.[User] SELECT * FROM 测试数据源.dbo.[User]

因为,两个表中都有自动增长的字段ID,如果复制所有的内容,也会导致复制ID字段的内容,而这会打乱系统自动增长的规律,可能会导致执行失败。



DECLARE @strVARCHAR(1000)

DECLARE @SqlstrVARCHAR(1000)

SET @str = ''

SELECT @str=@str+','+syscolumns.[name] FROM syscolumns WHERE syscolumns.id=object_id('User') and syscolumns.[name]<>'ID'

SET @str = stuff(@str,1,1,'')

这一段代码,查询User表中的所有名称不为ID的字段的名称,并用逗号分隔。

SET @str = stuff(@str,1,1,'')

这一句代码的功能是去除开始的逗号。

SET @str = 'INSERT INTO 测试目标.dbo.[User](' + @str + ') SELECT ' + @str + ' FROM 测试数据源.dbo.[User]'

这一句代码生成复制数据的命令。



DECLARE Ptr CURSOR

FOR

SELECT ID FROM 测试数据源.dbo.[User]

OPEN Ptr

DECLARE @ID INT



FETCH NEXT FROM Ptr INTO @ID

WHILE (@@FETCH_STATUS <> -1)

BEGIN

IF (@@FETCH_STATUS <> -2)

BEGIN

SET @Sqlstr = @str + ' WHERE ID=' + CONVERT(varchar, @ID)

EXEC(@Sqlstr)

DELETE FROM 测试数据源.dbo.[User] WHERE ID = @ID

END

FETCH NEXT FROM Ptr INTO @ID

END

CLOSE Ptr

DEALLOCATE Ptr

这一段代码,使用了多个游标,逐行的复制数据和删除数据,以实现移动数据的目的。

这里之所以采取一行一行的移动数据,主要是为了防止,在移动数据的过程中,又有了新的人员入库,插入了新的记录。一行一行的移动可以使得复制数据和删除数据可以一一对应。



最后可以把此存储过程放到作业中,使得它可以被周期运行,就可以实现自动的数据移动了。
打造民族品牌  铸就工控业绩
匿名用户
文章数:N/A
年度积分:0
历史总积分:0
注册时间:2012/1/10
发站内信
发表于:2012/1/10 20:18:05
#1楼
该用户被锁定,回复内容不予显示!

关于我们 | 联系我们 | 广告服务 | 本站动态 | 友情链接 | 法律声明 | 非法和不良信息举报

工控网客服热线:0755-86369299
版权所有 工控网 Copyright©2024 Gkong.com, All Rights Reserved

62.4004