谷歌公布初步报仇雪恨近义词必须。不行不行出代表性的表现下或大或小的好的话动不动就下定决心吧小剧场经常重复

如何取得刚插入数据库的数据的id&mysql
两条SQl语句
第一步 insert 语句
第二步 根据插入字段查询出id
即 select id from tab where
(关键条件,确保几个条件的组合是唯一的)
转自于:,仅供学习
SELECT & LAST_INSERT_ID();&
获得刚插入的id号,多客户端并发插入对取到的id号不会有问题,因为各线程独立。
,我也查到一种方法:&
select & @@session.
我们在写数据库程序的时候,经常会需要获取某个表中的最大序号数,
一般情况下获取刚插入的数据的id,使用select max(id) from table
是可以的。
但在多线程情况下,就不行了。
下面介绍三种方法
(1) getGeneratedKeys()方法:
Connection conn = ;
Serializable ret =
PreparedStatement state = .;
ResultSet rs=
&&&&&&&&&&&
state.executeUpdate();
&&&&&&&&&&&
rs = state.getGeneratedKeys();
&&&&&&&&&&&
if (rs.next()) {
&&&&&&&&&&&&&&&
ret = (Serializable) rs.getObject(1);
&&&&&&&&&&&
} catch (SQLException e) {
(2)LAST_INSERT_ID:
LAST_INSERT_ID
是与table无关的,如果向表a插入数据后,再向表b插入数据,LAST_INSERT_ID会改变。
在多用户交替插入数据的情况下max(id)显然不能用。
这就该使用LAST_INSERT_ID了,因为
LAST_INSERT_ID是基于Connection的,只要每个线程都使用独立的Connection对象,LAST_INSERT_ID函数将返
回该Connection对AUTO_INCREMENT列最新的insert or
update*作生成的第一个record的ID。这个值不能被其它客户端(Connection)影响,保证了你能够找回自己的 ID
而不用担心其它客户端的活动,而且不需要加锁。使用单INSERT语句插入多条记录,&
LAST_INSERT_ID返回一个列表。
(3)select @@IDENTITY:
String sql="select @@IDENTITY";
@@identity是表示的是最近一次向具有identity属性(即自增列)的表插入数据时对应的自增列的值,是系统定义的
全局变量。一般系统定义的全局变量都是以@@开头,用户自定义变量以@开头。比如有个表A,它的自增列是id,当向A表插入一行数据后,如果插入数据后自
增列的值自动增加至101,则通过select
@@identity得到的值就是101。使用@@identity的前提是在进行insert操作后,执行select
@@identity的时候连接没有关闭,否则得到的将是NULL值。
注:在java中使用last_insert_id();是要在一插入后就使用,也就是不能新建立Connection
比如insert建了一个
Connection,用last_insert_id()就要用同一个Connection,不能在两条查询语句(即“insert
into。。。”和"select
last_insert_id()")都使用getConn()创建新管道,正确的做法是insert语句getConn()创建了管道以
后,"select
last_insert_id()"就直接用全局变量的conn也就是创建好的同一管道查询才有效果,否则会返回0得不到新插入的自动增长列列号,切
忌!!!!!!!!!
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。Mysql存储过程查询结果赋值到变量的方法
Mysql存储过程查询结果赋值到变量的方法
把查询结果赋值到变量,大部分情况下使用游标来完成,但是如果明确知道查询结果只有一行(例如统计记录的数量,某个字段求和等),其实可以使用set或into的方式来实现赋值。示例代码:
drop table if exists test_
create table test_tbl (name varchar(20), status int(2));
insert into test_tbl values('abc', 1),('edf', 2),('xyz', 3);
drop procedure IF EXISTS pro_test_3;
delimiter //
create procedure pro_test_3()
DECLARE cnt INT DEFAULT 0;
select count(*) into cnt from test_
set @cnt = (select count(*) from test_tbl);
select count(*) into @cnt1 from test_
select @cnt1;
多个列的情况下似乎只能用 into 方式
select max(status), avg(status) into @max, @avg from test_
select @max, @
call pro_test_3();
(window.slotbydup=window.slotbydup || []).push({
id: '2467140',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467141',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467142',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467143',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467148',
container: s,
size: '1000,90',
display: 'inlay-fix'posts - 26,&
comments - 0,&
trackbacks - 0
如何才能写出高性能的SQL语句,以下的十三条法则值得你去注意。比如什么是执行计划?为什么要统一SQL语句的写法等等。
  1、 首先要搞明白什么叫执行计划?
  执行计划是数据库根据SQL语句和相关表的统计信息作出的一个查询方案,这个方案是由查询优化器自动分析产生的,比如一条SQL语句如果用来从一个10万条记录的表中查1条记录,那查询优化器会选择索引查找方式,如果该表进行了归档,当前只剩下5000条记录了,那查询优化器就会改变方案,采用全表扫描方式。
  可见,执行计划并不是固定的,它是个性化的。产生一个正确的执行计划有两点很重要:
  (1) SQL语句是否清晰地告诉查询优化器它想干什么?
  (2) 查询优化器得到的数据库统计信息是否是最新的、正确的?
  2、 统一SQL语句的写法
  对于以下两句SQL语句,程序员认为是相同的,数据库查询优化器认为是不同的。
1. select*fromdual
2. select*Fromdual
  其实就是大小写不同,查询分析器就认为是两句不同的SQL语句,必须进行两次解析。生成2个执行计划。所以作为程序员,应该保证相同的查询语句在任何地方都一致,多一个空格都不行!
  3、 不要把SQL语句写得太复杂
  我经常看到,从数据库中捕捉到的一条SQL语句打印出来有2张A4纸这么长。一般来说这么复杂的语句通常都是有问题的。我拿着这2页长的SQL语句去请教原作者,结果他说时间太长,他一时也看不懂了。可想而知,连原作者都有可能看糊涂的SQL语句,数据库也一样会看糊涂。
  一般,将一个Select语句的结果作为子集,然后从该子集中再进行查询,这种一层嵌套语句还是比较常见的,但是根据经验,超过3层嵌套,查询优化器就很容易给出错误的执行计划。因为它被绕晕了。像这种类似人工智能的东西,终究比人的分辨力要差些,如果人都看晕了,我可以保证数据库也会晕的。
  另外,执行计划是可以被重用的,越简单的SQL语句被重用的可能性越高。而复杂的SQL语句只要有一个字符发生变化就必须重新解析,然后再把这一大堆垃圾塞在内存里。可想而知,数据库的效率会何等低下。
  4、 使用临时表暂存中间结果
  简化SQL语句的重要方法就是采用临时表暂存中间结果,但是,临时表的好处远远不止这些,将临时结果暂存在临时表,后面的查询就在tempdb中了,这可以避免程序中多次扫描主表,也大大减少了程序执行中共享锁阻塞更新锁,减少了阻塞,提高了并发性能。
  5、 OLTP系统SQL语句必须采用绑定变量
1. select*fromorderheaderwherechangetime&&2010-10-2000:00:01&
2. select*fromorderheaderwherechangetime&&2010-09-2200:00:01&
  以上两句语句,查询优化器认为是不同的SQL语句,需要解析两次。如果采用绑定变量
1. select*fromorderheaderwherechangetime&@chgtime
  @chgtime变量可以传入任何值,这样大量的类似查询可以重用该执行计划了,这可以大大降低数据库解析SQL语句的负担。一次解析,多次重用,是提高数据库效率的原则。
  6、 绑定变量窥测
  事物都存在两面性,绑定变量对大多数OLTP处理是适用的,但是也有例外。比如在where条件中的字段是倾斜字段的时候。
  倾斜字段指该列中的绝大多数的值都是相同的,比如一张人口调查表,其中民族这列,90%以上都是汉族。那么如果一个SQL语句要查询30岁的汉族人口有多少,那民族这列必然要被放在where条件中。这个时候如果采用绑定变量@nation会存在很大问题。
  试想如果@nation传入的第一个值是汉族,那整个执行计划必然会选择表扫描。然后,第二个值传入的是布依族,按理说布依族占的比例可能只有万分之一,应该采用索引查找。但是,由于重用了第一次解析的汉族的那个执行计划,那么第二次也将采用表扫描方式。这个问题就是著名的绑定变量窥测,建议对于倾斜字段不要采用绑定变量。
  7、 只在必要的情况下才使用begin tran
  SQL Server中一句SQL语句默认就是一个事务,在该语句执行完成后也是默认commit的。其实,这就是begin tran的一个最小化的形式,好比在每句语句开头隐含了一个begin tran,结束时隐含了一个commit。
  有些情况下,我们需要显式声明begin tran,比如做插、删、改操作需要同时修改几个表,要求要么几个表都修改成功,要么都不成功。begin tran 可以起到这样的作用,它可以把若干SQL语句套在一起执行,最后再一起commit。好处是保证了数据的一致性,但任何事情都不是完美无缺的。Begin tran付出的代价是在提交之前,所有SQL语句锁住的资源都不能释放,直到commit掉。
  可见,如果Begin tran套住的SQL语句太多,那数据库的性能就糟糕了。在该大事务提交之前,必然会阻塞别的语句,造成block很多。
  Begin tran使用的原则是,在保证数据一致性的前提下,begin tran 套住的SQL语句越少越好!有些情况下可以采用触发器同步数据,不一定要用begin tran。
  8、 一些SQL查询语句应加上nolock
  在SQL语句中加nolock是提高SQL Server并发性能的重要手段,在oracle中并不需要这样做,因为oracle的结构更为合理,有undo表空间保存数据前影,该数据如果在修改中还未commit,那么你读到的是它修改之前的副本,该副本放在undo表空间中。这样,oracle的读、写可以做到互不影响,这也是oracle广受称赞的地方。SQL Server 的读、写是会相互阻塞的,为了提高并发性能,对于一些查询,可以加上nolock,这样读的时候可以允许写,但缺点是可能读到未提交的脏数据。使用nolock有3条原则。
  (1) 查询的结果用于插、删、改的不能加nolock !
  (2) 查询的表属于频繁发生页分裂的,慎用nolock !
  (3) 使用临时表一样可以保存数据前影,起到类似oracle的undo表空间的功能,
  能采用临时表提高并发性能的,不要用nolock 。
  9、 聚集索引没有建在表的顺序字段上,该表容易发生页分裂
  比如订单表,有订单编号orderid,也有客户编号contactid,那么聚集索引应该加在哪个字段上呢?对于该表,订单编号是顺序添加的,如果在orderid上加聚集索引,新增的行都是添加在末尾,这样不容易经常产生页分裂。然而,由于大多数查询都是根据客户编号来查的,因此,将聚集索引加在contactid上才有意义。而contactid对于订单表而言,并非顺序字段。
  比如张三的contactid是001,那么张三的订单信息必须都放在这张表的第一个数据页上,如果今天张三新下了一个订单,那该订单信息不能放在表的最后一页,而是第一页!如果第一页放满了呢?很抱歉,该表所有数据都要往后移动为这条记录腾地方。
  SQL Server的索引和Oracle的索引是不同的,SQL Server的聚集索引实际上是对表按照聚集索引字段的顺序进行了排序,相当于oracle的索引组织表。SQL Server的聚集索引就是表本身的一种组织形式,所以它的效率是非常高的。也正因为此,插入一条记录,它的位置不是随便放的,而是要按照顺序放在该放的数据页,如果那个数据页没有空间了,就引起了页分裂。所以很显然,聚集索引没有建在表的顺序字段上,该表容易发生页分裂。
  曾经碰到过一个情况,一位哥们的某张表重建索引后,插入的效率大幅下降了。估计情况大概是这样的。该表的聚集索引可能没有建在表的顺序字段上,该表经常被归档,所以该表的数据是以一种稀疏状态存在的。比如张三下过20张订单,而最近3个月的订单只有5张,归档策略是保留3个月数据,那么张三过去的15张订单已经被归档,留下15个空位,可以在insert发生时重新被利用。在这种情况下由于有空位可以利用,就不会发生页分裂。但是查询性能会比较低,因为查询时必须扫描那些没有数据的空位。
  重建聚集索引后情况改变了,因为重建聚集索引就是把表中的数据重新排列一遍,原来的空位没有了,而页的填充率又很高,插入数据经常要发生页分裂,所以性能大幅下降。
  对于聚集索引没有建在顺序字段上的表,是否要给与比较低的页填充率?是否要避免重建聚集索引?是一个值得考虑的问题!
  10、加nolock后查询经常发生页分裂的表,容易产生跳读或重复读
  加nolock后可以在插、删、改的同时进行查询,但是由于同时发生插、删、改,在某些情况下,一旦该数据页满了,那么页分裂不可避免,而此时nolock的查询正在发生,比如在第100页已经读过的记录,可能会因为页分裂而分到第101页,这有可能使得nolock查询在读101页时重复读到该条数据,产生重复读。同理,如果在100页上的数据还没被读到就分到99页去了,那nolock查询有可能会漏过该记录,产生跳读。
  上面提到的哥们,在加了nolock后一些操作出现报错,估计有可能因为nolock查询产生了重复读,2条相同的记录去插入别的表,当然会发生主键冲突。
  11、使用like进行模糊查询时应注意
  有的时候会需要进行一些模糊查询比如
1. select*fromcontactwhereusernamelike&%yue%&
  关键词%yue%,由于yue前面用到了%,因此该查询必然走全表扫描,除非必要,否则不要在关键词前加%,
  12、数据类型的隐式转换对查询效率的影响
  sql server2000的数据库,我们的程序在提交sql语句的时候,没有使用强类型提交这个字段的值,由sql server 2000自动转换数据类型,会导致传入的参数与主键字段类型不一致,这个时候sql server 2000可能就会使用全表扫描。Sql2005上没有发现这种问题,但是还是应该注意一下。
  13、SQL Server 表连接的三种方式
  (1) Merge Join
  (2) Nested Loop Join
  (3) Hash Join
  SQL Server 2000只有一种join方式Nested Loop Join,如果A结果集较小,那就默认作为外表,A中每条记录都要去B中扫描一遍,实际扫过的行数相当于A结果集行数x B结果集行数。所以如果两个结果集都很大,那Join的结果很糟糕。
  SQL Server 2005新增了Merge Join,如果A表和B表的连接字段正好是聚集索引所在字段,那么表的顺序已经排好,只要两边拼上去就行了,这种join的开销相当于A表的结果集行数加上B表的结果集行数,一个是加,一个是乘,可见merge join 的效果要比Nested Loop Join好多了。
  如果连接的字段上没有索引,那SQL2000的效率是相当低的,而SQL2005提供了Hash join,相当于临时给A,B表的结果集加上索引,因此SQL2005的效率比SQL2000有很大提高,我认为,这是一个重要的原因。
  总结一下,在表连接时要注意以下几点:
  (1) 连接字段尽量选择聚集索引所在的字段
  (2) 仔细考虑where条件,尽量减小A、B表的结果集
  (3) 如果很多join的连接字段都缺少索引,而你还在用SQL Server 2000,赶紧升级吧。
阅读(...) 评论()查看: 3000|回复: 10
select from where 查找两个变量条件到底怎么写
阅读权限20
在线时间 小时
sql4 = &Select * from 生产计划 Where 物料编码 = '& + q + &' and 需求日期 = # & & p & & #&
q 为文本格式,P 为日期格式,查询数据库为:ACCESS
单独使用任意一个条件都可以的,用 and 连在一起就报错,哪位老师知道
阅读权限20
在线时间 小时
如果用 or 就可以, 为什么 用 and 就不行
阅读权限95
在线时间 小时
用&代替+试试看:sql4 = &Select * from 生产计划 Where 物料编码 = '& & q & &' and 需求日期 = #& & p & &#&复制代码
阅读权限20
在线时间 小时
zhaogang1960 发表于
用&代替+试试看:
老师,不行的,
如果用 or 就可以, 为什么 用 and 就不行
会不会是没有符合条件,就报错呀
阅读权限20
在线时间 小时
老师,不行的,
如果用 or 就可以, 为什么 用 and 就不行
会不会是没有符合条件,就报错呀
阅读权限95
在线时间 小时
sdhwy 发表于
老师,不行的,
如果用 or 就可以, 为什么 用 and 就不行
会不会是没有符合条件,就报错呀
不会报错,这样试试看:
& & Set rs = cnn.Execute(SQL)
& & If Not rs.EOF Then Range(&a2&).CopyFromRecordset rs
阅读权限20
在线时间 小时
本帖最后由 sdhwy 于
23:45 编辑
sql4 = &Select * from 生产计划 Where 需求日期&=# & & p & & # and 物料编码 = '& + q + &'&
arr4 = mydata.筛选结果(sql4)
'下面是类模块
Function 筛选结果(sq As String)
Dim conn As New Connection
Dim rst As New Recordset
conn.Open &provider=Microsoft.ACE.OLEDB.12.0;data source=& & ThisWorkbook.Path & &/Database/ywang.accdb&
Set rst = conn.Execute(sq)
筛选结果 = rst.GetRows
conn.Close
Set conn = Nothing
End Function
问题就出在两个条件返回是空值,如果有数值就不报错
阅读权限20
在线时间 小时
If Not rs.EOF Then Range(&a2&).CopyFromRecordset rs
老师,这句是什么意思,应加在那里
阅读权限95
在线时间 小时
sdhwy 发表于
If Not rs.EOF Then Range(&a2&).CopyFromRecordset rs
老师,这句是什么意思,应加在那里
我是告诉你判断方法,你的程序不一定需要复制数据,如果你直接从查询中取数据,必须判断一下该查询是否有记录,If Not rs.EOF Then就是判断方法
阅读权限95
在线时间 小时
sdhwy 发表于
sql4 = &Select * from 生产计划 Where 需求日期
请参考:Function 筛选结果(sq As String)
Dim conn As New Connection
Dim rst As New Recordset
conn.Open &provider=Microsoft.ACE.OLEDB.12.0;data source=& & ThisWorkbook.Path & &/Database/ywang.accdb&
Set rst = conn.Execute(sq)
If Not rst.EOF Then 筛选结果 = rst.GetRows
conn.Close
Set conn = Nothing
End Function
Sub test()
& & Dim arr
& & arr = 筛选结果(sq)
& & If IsArray(arr) Then
& && &&&MsgBox &查询有记录&
& & Else
& && &&&MsgBox &查询无记录&
& & End If
End Sub
复制代码
玩命加载中,请稍候
玩命加载中,请稍候
Powered by
本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任! & & 本站特聘法律顾问:徐怀玉律师 李志群律师

我要回帖

更多关于 报仇雪恨中的雪的意思 的文章

 

随机推荐