sql2000临时表的怪问题(100分)

  • 主题发起人 主题发起人 gxw
  • 开始时间 开始时间
G

gxw

Unregistered / Unconfirmed
GUEST, unregistred user!
function AdoExec(SqlText: string): boolean;
begin
with Form1.ADOQuery1 do
try
Close; Connection:=Form1.ADOConnection1; Sql.clear; Sql.add(sqlText); ExecSql;
Result:=True;
except
on e:exception do
begin
Result:=False;
ShowMessage(e.Message);
end;
end
end;

function CreateTable(TableName: string; StruID: integer): Boolean;
begin
case StruID of
0: Result:=AdoExec('Create Table '+TableName+'(Code VarChar(12) PRIMARY KEY,Name VarChar(40),Unit VarChar(8),kind VarChar(20))');
1: Result:=AdoExec('Create Table '+TableName+'(Id Int IDENTITY(1,1) PRIMARY KEY,Code VarChar(12),Billno VarChar(12))');
2: ....
3: ....
else
Result:=False;
end;
end;

function CreateTempTable(TableStruId: integer): string;
begin
Randomize;
Result:='#Temp'+inttostr(random(100000));
CreateTable(Result,TableStruId);
end;


//------------------------------------------------------------------------------
procedure TForm1.Button1Click(Sender: TObject);//-----Form1测试
var
TableName: string;
begin
TableName:=CreateTempTable(1);
ShowMessage(TableName);
//--------------检查tempdb内已创建了临时表TableName
end;


procedure TForm2.Button1Click(Sender: TObject);//-----Form2测试
var
TableName: string;
begin
TableName:=CreateTempTable(1);
ShowMessage(TableName);
//------------没报错,但查询分析器看并没有临时表被创建,其余窗口测试情况均相同。为何Form1就可以?
end;
 
这个我也不知道怎么说,不过如果你在查询分析器中同时打开A,B查询窗口,如果在A窗口中创建1个临时表,这个临时表在B窗口中是不可见的,可能你的问题就是这个原因吧。
 
谢跟帖。您说的大概是指本地临时表#和全局临时表##的区别。但就算不用查询分析器,在Form2放个adoquery1运行程序也一样:

procedure TForm2.Button1Click(Sender: TObject);//-----Form2测试
var
TableName: string;
begin
TableName:=CreateTempTable(1);
with adoquery1 do
begin
close;
connection:=Form1.ADOConnection1;
sql.clear;
sql.add('select * from '+TempFile);
Open; //运行到此报错:对象名'#Temp****'无效。我晕!
end;
end;
 
sql.add('select * from '+TempFile);
Open; //运行到此报错:对象名'#Temp****'无效。我晕!
***********************************************************
上面TempFile是什么?
 
非全局临时表只存在于创建它的连接中,
你Open一个AdoConnection是一个连接,打开一个查询分析器又是另外一个连接。
要看有没有创建,打开事件探查器。
 
to dcx0026:
抱歉,错手把TableName打成TempFile了。应该是
sql.add('select * from '+TableName);
 
有点怀疑本机安装的sql2000l版本是否有bug.这是绿色简化版,改过的,安装文件只有12M左右。
 
谢跟帖。您说的大概是指本地临时表#和全局临时表##的区别。但就算不用查询分析器,在Form2放个adoquery1运行程序也一样:

procedure TForm2.Button1Click(Sender: TObject);//-----Form2测试
var
TableName: string;
begin
TableName:=CreateTempTable(1);
with adoquery1 do
begin
close;
connection:=Form1.ADOConnection1;
sql.clear;
sql.add('select * from '+TableName);
Open; //运行到此报错:对象名'#Temp****'无效。我晕!
end;
end;
******************************************************************
就你贴出来的代码,运行应该没什么问题。
可能是简化版的问题?
 
无果,暂时先结帖了。谢谢两位跟帖。先不用系统临时表了,直接建普通表,用完显式删除:D
 
回答1:[:D]

不管是局部临时表或者全局临时表。
都会存放在tempdb中的。

不过因为全局临时表同名的只能有一个,因此SQL Server不要做出任何特别的处理。
但是由于局部临时表是基于session存在的,每个session拥有自己的局部临时表,那怕它的名字都是一样但却是不同的对象。因此SQL Server会做出一些特殊的处理,tempdb的sysobjects在存放局部临时表的时候,它会在局部临时表的后面加上一些后缀,不过每个对象的objectid是不一样的,SQL Server可以通过objectid指向正确的对象。
这就是为什么在自己的DB下用select * from #temp1也能找到正确的对象一样。

只要执行下面的语句,你们就会知道局部临时表仍然是存放在tempdb中的:
select * from tempdb.dbo.sysobjects where id = object_id('tempdb.dbo.#temp1')

回答2:[:D]
use tempdb;
select name from sysobjects;
就可以看到建立的临时表
生存期间
如果不drop table,通过重新启动服务可以清除掉临时表
局部临时表的清除或者在另一个会话中使用没什么意义,因为局部临时表本身就是基于会话的。可以参照使用全局临时表。
如何在临时表中使用自定义的数据类型。
在tempdb中,只有sql server内置的数据类型,使用自定义数据类型需要在master库中书写一个服务启动自动运行的存储过程,存储过程的工作就是建立自定义数据类型到tempdb中,例如:
CREATE PROCEDURE [dbo].[sp_AddDefinedDataTypeToTempDb] AS
exec('use tempdb
if exists (select * from dbo.systypes where name = N''utAccountNum'')
exec sp_droptype N''utAccountNum''

EXEC sp_addtype N''utAccountNum'', N''varchar (20)'', N''null''
')
GO

exec sp_procoption N'sp_AddDefinedDataTypeToTempDb', N'startup', N'true'
GO


个人认为还是搞清楚比较好![:D]
 
后退
顶部