| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 2363 人关注过本帖
标题:自动编码可以写在子程序中嘛?
只看楼主 加入收藏
hu9jj
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:红土地
等 级:贵宾
威 望:400
帖 子:11857
专家分:43421
注 册:2006-5-13
收藏
得分:0 
单个的PRG文件可以直接调用的。

活到老,学到老!http://www.(该域名已经被ISP盗卖了)E-mail:hu-jj@
2016-01-12 19:25
liuxingang28
Rank: 11Rank: 11Rank: 11Rank: 11
来 自:山东济南
等 级:贵宾
威 望:47
帖 子:658
专家分:2180
注 册:2014-2-7
收藏
得分:0 
在实际应用中,对于自动编号字段的处理有三种常用方法:
1. 将字段类型设置为 Integer(AutoInc)即可,适用于对数据值不敏感仅作为主关键字的字段,属于“一劳永逸”型。
   优点:无需人工干预,系统自动递增。
   缺点:数据类型只能是Integer(整型)。若启用了数据缓冲,而又放弃数据(通过TableRevert()函数)时,会出现空号
2. 在添加字段前,先统计表中该字段的最大值,再对该值加1作为新编号,属于“现学现用”型
   优点:算法简单,可处理数值型和字符型字段
   缺点:不适用于多用户环境。多个用户同时操作时,有可能出现重号现象。若用户一定要使用该方法,则可为该字段建立主索引或侯选索引,并在保存记录时捕获错误。还有一个缺点是,当表记录很多时,查找表的最大值会很耗费时间。
   注意:统计字段的最大值时,使用 Select MAX(字段) From 表,要比 Calculate MAX(字段)好。因为前者会忽略表的过滤条件(Set Filter To),而后者受过滤条件的影响。
3. 完美型,即能自动编号,又支持数值型和字符型字段,同时,效率还很高。
   第一步:建立一个表 AotoNumber 用于保存字段的当前编号
           CREATE TABLE AutoNumber (表 c(20),字段 c(20),类型 c(1),长度 i,值 i)
           INSERT INTO AutoNumber VALUES ('员工表','编号','C',6,1)
           说明:返回数值型编号时,设“类型”为 N;返回字符型编号时,设类型为 C,且左边补零。“长度”字段仅用于字符型编号
   第二步:编写一个获取编号的函数 Newid.prg,内容如下:
程序代码:
********************************************************************
* 功能:获取编号
* 参数:tcTable [color=#808080]- 表名[/color]
*       tcField [color=#808080]- 字段名[/color]
* 返回:获取编号失败时,返回 [color=#0000FF]NULL;否则,返回新编号[/color]
********************************************************************
LPARAMETERS tcTable,tcField
LOCAL nSelect,vNewid
nSelect = SELECT()        && 保存工作区
vNewid = NULL             && 指定编号初值
IF !USED('AutoNumber')    && 打开编号表
    USE AutoNumber IN 0
ENDIF
SELECT AutoNumber         && 定位记录
LOCATE FOR ALLT(表) == ALLT(tcTable) AND ALLT(字段) == ALLT(tcField)
IF FOUND() AND RLOCK()    && 锁定表防止其他用户同时取编号
    vNewid =&& 取编号值
    REPLACEWITH+ 1    && 编号累加 1
    UNLOCK                && 解锁,此时其他用户可以获取编号
    IF 类型 = 'C'         && 对于字符型编号作进一步处理
        vNewid = PADL(vNewid,长度,'0')
    ENDIF
ENDIF
SELECT (nSelect)          && 恢复工作区
RETURN vNewid             && 返回编号值
   第三步:调用函数获取编号
          cValue = Newid('员工表','编号')
           IF ISNULL(cValue)
              MESSAGEBOX('获取编号失败',16,'提示')
           ELSE
              REPLACE 编号 WITH m.cValue IN 员工表
           ENDIF

[此贴子已经被作者于2016-1-13 10:32编辑过]


泉城飞狐
2016-01-13 10:24
mywisdom88
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:191
帖 子:3147
专家分:8408
注 册:2015-3-25
收藏
得分:0 
以下是引用liuxingang28在2016-1-13 10:24:30的发言:

在实际应用中,对于自动编号字段的处理有三种常用方法:
1. 将字段类型设置为 Integer(AutoInc)即可,适用于对数据值不敏感仅作为主关键字的字段,属于“一劳永逸”型。
   优点:无需人工干预,系统自动递增。
   缺点:数据类型只能是Integer(整型)。若启用了数据缓冲,而又放弃数据(通过TableRevert()函数)时,会出现空号
2. 在添加字段前,先统计表中该字段的最大值,再对该值加1作为新编号,属于“现学现用”型
   优点:算法简单,可处理数值型和字符型字段
   缺点:不适用于多用户环境。多个用户同时操作时,有可能出现重号现象。若用户一定要使用该方法,则可为该字段建立主索引或侯选索引,并在保存记录时捕获错误。还有一个缺点是,当表记录很多时,查找表的最大值会很耗费时间。
   注意:统计字段的最大值时,使用 Select MAX(字段) From 表,要比 Calculate MAX(字段)好。因为前者会忽略表的过滤条件(Set Filter To),而后者受过滤条件的影响。
3. 完美型,即能自动编号,又支持数值型和字符型字段,同时,效率还很高。
   第一步:建立一个表 AotoNumber 用于保存字段的当前编号
           CREATE TABLE AutoNumber (表 c(20),字段 c(20),类型 c(1),长度 i,值 i)
           INSERT INTO AutoNumber VALUES ('员工表','编号','C',6,1)
           说明:返回数值型编号时,设“类型”为 N;返回字符型编号时,设类型为 C,且左边补零。“长度”字段仅用于字符型编号
   第二步:编写一个获取编号的函数 Newid.prg,内容如下:********************************************************************
* 功能:获取编号
* 参数:tcTable - 表名
*       tcField - 字段名
* 返回:获取编号失败时,返回 NULL;否则,返回新编号
********************************************************************
LPARAMETERS tcTable,tcField
LOCAL nSelect,vNewid
nSelect = SELECT()        && 保存工作区
vNewid = NULL             && 指定编号初值
IF !USED('AutoNumber')    && 打开编号表
    USE AutoNumber IN 0
ENDIF
SELECT AutoNumber         && 定位记录
LOCATE FOR ALLT(表) == ALLT(tcTable) AND ALLT(字段) == ALLT(tcField)
IF FOUND() AND RLOCK()    && 锁定表防止其他用户同时取编号
    vNewid = 值           && 取编号值
    REPLACE 值 WITH 值 + 1    && 编号累加 1
    UNLOCK                && 解锁,此时其他用户可以获取编号
    IF 类型 = 'C'         && 对于字符型编号作进一步处理
        vNewid = PADL(vNewid,长度,'0')
    ENDIF
ENDIF
SELECT (nSelect)          && 恢复工作区
RETURN vNewid             && 返回编号值   第三步:调用函数获取编号
          cValue = Newid('员工表','编号')
           IF ISNULL(cValue)
              MESSAGEBOX('获取编号失败',16,'提示')
           ELSE
              REPLACE 编号 WITH m.cValue IN 员工表
           ENDIF

感觉可以,没测试。
对于第3方法,要是我用SQL2000的数据库呢?用什么方法来避免。
我目前的方法是:
1、增加1条记录时,先查最大的记录号,然后加1,然后用PADL(),然后 sqlexec(nhandle,'insert into ......')
2、批量增加记录时,先查最大的记录号,然后加1,然后用PADL(),然后 sqlexec(nhandle,'insert into ......'),再查+1后是否存在,然后再sqlexec(nhandle,'insert into ......')
由于用户不多,在同时增加数据的机会不大,目前还没出现重复号,我每次增加1个,就要查询这个是否存在,好像很费资源。
不知道有没其他更加好的

2016-01-13 10:48
liuxingang28
Rank: 11Rank: 11Rank: 11Rank: 11
来 自:山东济南
等 级:贵宾
威 望:47
帖 子:658
专家分:2180
注 册:2014-2-7
收藏
得分:0 
回复 13楼 mywisdom88
SQL Server 2000中的表字段也可以设成自动递增(AutoInc)

泉城飞狐
2016-01-13 11:15
mywisdom88
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:191
帖 子:3147
专家分:8408
注 册:2015-3-25
收藏
得分:0 
我用的是字符字段 编号 varchar(10)
每次增加编号是,都是先查询当前最大值
bh=""
sqlexec(nhandle,'select max(编号) as 编号 from 资料表','sql_table')
if used("sql_table")
   bh=iif(isnull(sql_table.编号),"",allt(sql_table.编号))
   use in sql_table
endif
bh=padl(val(bh)+1,10,"0")
我每次增加1个编号时都要这样做,然后才
sqlexec(nhandle,'insert into 资料表(编号) values(?bh)')
由于读最大编号到增加记录的过程中,有段时间,要是还有1台电脑,在这时间读取最大编号,他可能读取到的最大编号是和我一样的,怎么避免这个情况

2016-01-13 11:38
快速回复:自动编码可以写在子程序中嘛?
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.019132 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved