SQL语句大全

发布时间:2019-12-12 03:23    浏览次数 :

[返回]

问题:
开发环境:delphi7se + mysql 5.0.67 + dbexpress 2.0 + mysql50open
开发控件:tsimpledataset+datasoure+dbgrid/dbedit
权限:mysql已经授权用户有select/update权限.
但是如果数据有修改,applyupdates(0)始终报告出错.
加入outputdebugstring(pchar(strList)),在view/debug windows/event log中监测到两条错误信息:
"Record not found or changed by another user."
"Unable to find record. No key specified."

SQL即结构化查询语言(Structured Query Language),是一种特殊目的的编程语言,是一种数据库查询和程序设计语言,用于存取数据以及查询、更新和管理关系数据库系统;同时也是数据库脚本文件的扩展名。SQL语句无论是种类还是数量都是繁多的,很多语句也是经常要用到的,SQL查询语句就是一个典型的例子,无论是高级查询还是低级查询,SQL查询语句的需求是最频繁的。

解决方法:
from

基础

測試的 Form 內放了 TSQLConnection、TSQLQuery、TDataSetProvider、TClientDataSet、TDataSource、TDBGrid、TDBNavigator 各一個
TSQLConnection 指定 Connection Name 使它和資料庫連接
TSQLQuery 連上 TSQLConnection, 指定 SQL (為最簡單的 SELECT * FROM ...), 然後在TSQLQuery的fields属性中添加所有所有的字段, 除了 PK 不動, 其它的列的 ProviderFlags 去掉 pfInWhere(注意喔, PK 的 pfInWhere 要保持勾選喔, 非 PK 的則去掉)
TDataSetProvider 連上 TSQLQuery
TClientDataSet 連上 TDataSetProvider, 並撰寫 AfterPost (內容就是資料庫交易和 ApplyUpdate) 及 ReconcileError (呼叫 HandleReconcileError)
TDataSource,TDBGrid,TDBNavigater 設好基本屬性..

创建数据库

Build 出執行檔後, 執行兩份(A和B), 進行測試...
針對同一筆資料, A 先異動(PK不異動), 儲存後, B 異動(不管含不含PK), 可成功的儲存 (A,B都按一下更新鈕, 會發現資料以 B 的為最新)
針對同一筆資料, A 先異動(包含PK), 儲存後, B 異動(不管含不含PK), 出現 "Record not found or changed by another user" 訊息
按取消, 或者選修正並將PK值改成A所輸入的新PK值, 即可通過

创建之前判断该数据库是否存在

原因:
众说纷纭.但基本有两点需要注意:
引用:"ClientDataSet提交时出现"Record not found or changed by another user"错误提示
分析原因可能是找不到更新数据,从网上搜索到大致原因有一下几个方面:
1、没有主键
2、某些字段不能识别
某些提供解决方案也无非是设置DSP的UpdateMode属性,去掉字段的一些默认值
这些问题,我仔细检查了一下,感觉不可能存在,仔细分析原因:我更新记录是分两种方式
一种是:clientdataset.append;
....
提交后再更新
另外一种是大批量插入表,然后打开数据集更新
而第一种方案不存在这个问题,我开始分析第2种方案可能存在的问题。有如下语句:
INSERT INTO tableA (field1,field2) SELECT field1,'' FROM tableb
前几天发现ClientDataSet的CommandText用SELECT ''是不能识别的,提示无效的参数
我想是不是这个原因造成,所以将''改为' '一些正常。"

if exists (select * from sysdatabases where name='databaseName')

根据mysql的日志分析,我碰到的是第2种情况,但因为字段众多,修改起来比较麻烦,同时我也不想手工写sql语句.
在按照上面的方法修改前datasnap回传的sql语句是
update students set
曾用名 = '99'
where
班级 = '1' and
注册学号 = '080801031286' and
身份证号 = 'xxx' and
姓名 = '顾xx' and
曾用名 = '' and
性别 = '女' and
民族 = '汉族' and
籍贯省 = '江苏' and
籍贯市县 = 'xxx市' and
家庭地址 = 'xxx路51号2单元702' and
联系电话 = '1335' and
毕业学校 = 'xxx' and
父亲姓名 = '' and
父亲单位 = '' and
母亲姓名 = '' and
母亲单位 = ''
可以看到,窗体中所涉及到的所有字段,无论是否修改,全部都回传到mysql,累赘.
在按照上面的方法修改后datasnap回传的sql语句是
update students set
曾用名 = '11'
where
注册学号 = '080801031285'

drop database databaseName

update students set
曾用名 = 'qq',
父亲姓名 = 'aa',
父亲单位 = 'bbbbb',
母亲姓名 = 'cc',
母亲单位 = 'ddddd'
where
注册学号 = '080801031286'

go

COMMIT
现在,只涉及到窗体中数值发生修改的字段.
两相对比可以看出,后面的sql语句更简单,效率更高.

Create DATABASE databasename

另外老外的说法也有道理,这是mysql非标准sql造成的:
As I posted in a reply to this thread in dbexpress, I suspect the
posters problem is the fact that MySQL does not follow the standard
convention of returning the number of records affected by an update.
Most DBMS's return the number of records found that matched the WHERE
clause in the update SQL statement. MySQL doesn't do this. It returns
the number of records that had data changed by the SQL update
statement. So, if an update SQL WHERE clause matches one record, but
the UPDATE clause does not actually make changes to the column values
(for example SET MyField = '123' and MyField already contains '123'),
MySQL returns a RowsAffected count of zero. MIDAS interprets this as
an unable to find record error.

on primary-- 默认就属于primary文件组,可省略

最终结论:
引用
"我想, 問題就出在 TSimpleDataSet.
李維先生在研討會和著作的書籍中也建議大家使用 TSQLQuery+TDataSetProvider+TClientDataSet 的方式
雖然 TSimpleDataSet 一樣是由這三個元件包裝而成, 但許多 Property Method Event 被隱藏了.
當修改 TSimpleDataSet 拉出來的 TField 的 ProviderFlags 時, 實際上是修改到了 TClientDataSet 這一層的 TField.ProviderFlags
而我們要修改的應該是 TSQLQuery 的 TField.ProviderFlags
因此不論你怎麼改, TSQLMonitor 所觀察到的 SQL 語句都不受影響
所以建議你棄用 TSimpleDataSet
我個人一向不使用 TSimpleDataSet (以李先生的建議是, 對於一些 Simple 的事務, 可交由它處理, 其它的事務還是以分成三元件的撰寫方式為佳)
使用 TSQLQuery+TDataSetProvider+TClientDataSet 還有別的好處
當要改用 ADO 時, 只要把 TSQLQuery 換成 TADOQuery 即可
當要改成三層式時, 只要把 TSQLQuery 和 TDataSetProvider 搬到中間層即可"

方法2:(未试过,备用)
from
''record not found or changed by another user'',这个错误是我在做项目时,遇到的问题,找了一些参考才解决。如下:
所用的控件有:TDataSetProvider,TADOQuery,TClientDataSet
1.当 DataSetProvider.UpdateMode=upWhereAll 时,update时 where 是指定全部字段,比如,你有a、b、c 3个字段,修改了c字段,在app server中修改的命令是update ... set c=新c where a=旧a and b=旧b and c=旧c
如果 旧的a、b、c之一 已经被其他人改掉了,那where就找不到合适的记录来修改了。所以报告“记录被其他人修改”,这个问题和“锁定”是无关的。

/*--数据文件的具体描述--*/

2.当 DataSetProvider.UpdateMode=upWhereKeyOnly 时,update时 where 是指定key字段,比如,
你有a、b、c 3个字段,修改了c字段,a是key field在app server中修改的命令是
update ... set c=新c where a=旧a (只比较a字段)你的程序应该设计为客户修改不到主键字段的值,这样
你的客户只能修改到其他字段的值,其他字段不会出现在where中,就不会出现你说的问题了。

name=‘databasename_data’,-- 主数据文件的逻辑名称

(用第2种方法解决,注意如果你的表原来没有主键的,需要双击dataset,添加你的所有field,在有唯一值的field的 ProviderFlasgs 属性里面 InKey 设置为 true (该field必须是有唯一值的,能相当于主键的,也就是能唯一确定该行记录的),TADOQuery,TClientDataSet控件里的唯一值的field字都要设置InKey为true)

filename=‘'所存位置:databasename_data.mdf’, -- 主数据文件的物理名称

作者“清风乱翻书”

size=数值mb, --主数据文件的初始大小

: 开发环境:delphi7se + mysql 5.0.67 + dbexpress 2.0 + mysql50open 开发控件:tsimpledataset+datasoure+dbgrid/dbedit 权限:mysql已经授权用户有select/update权限...

maxsize=数值mb, -- 主数据文件增长的最大值

filegrowth=数值%--主数据文件的增长率

log on

/*--日志文件的具体描述,各参数含义同上--*/