ALTER PROCEDURE [dbo].[Sp_GetHeatPumpData] (@CurrentDate Char(10))
as
Begin IF OBJECT_ID(N'tempdb..#ReturnTable', N'U') IS NOT NULL
DROP TABLE #ReturnTable;
问题一:这一段是什么意思?
难道有“#”就表示是临时表么???
Create Table #ReturnTable
(
DPHour int;
DPValue Decimal(18,2)
);问题二:如何将从“不同表中”查询出来的“记录(结构一样,“DPHour和DPValue”两个字段)”,插入到这个临时表中?
as
Begin IF OBJECT_ID(N'tempdb..#ReturnTable', N'U') IS NOT NULL
DROP TABLE #ReturnTable;
问题一:这一段是什么意思?
难道有“#”就表示是临时表么???
Create Table #ReturnTable
(
DPHour int;
DPValue Decimal(18,2)
);问题二:如何将从“不同表中”查询出来的“记录(结构一样,“DPHour和DPValue”两个字段)”,插入到这个临时表中?
以一个井号 (#) 开头的那些表名。只有在创建本地临时表的连接上才能看到这些表,链接断开时临时表即被删除(本地临时表为创建它的该链接的会话所独享)或者这样说局部临时表是有当前用户创建的,并且只有当前用户的会话才可以访问。
如果本地临时表由存储过程创建或由多个用户同时执行的应用程序创建(其实可看作是不同的链接,不同的会话),则数据库引擎必须能够区分由不同用户创建的表。为此,数据库引擎在内部为每个本地临时表的表名追加一个数字后缀。存储在 tempdb 的 sysobjects 表中的临时表,其全名由 CREATE TABLE 语句中指定的表名和系统生成的数字后缀组成。为了允许追加后缀,为本地临时表指定的 table_name 不能超过 116 个字符。
对于本地临时表来说,需要注意在不同情形下应用本地临时表其删除的实际。如假设数据库在执行一个存储过程的时候建立了本地临时表。那么此时这个本地临时表并不是在会话终止的时候自动删除,而是在这个存储过程执行完毕后就会删除。这是什意思呢?也就是说,用户发起的某个会话,为了执行一个特殊的作业(如用户的这个会话调用了某个存储过程)。此时其实就是会话再创建一个子会话的过程。在这种情况下需要注意的是,子会话创建的本地临时表只在子会话内部有效。当这个子会话终止的时候(存储过程执行完毕),此时这个临时表就会自动删除。即对于调用这个子会话的会话来说,这个其子会话的创建的临时表对于其也是无效的,因为临时表已经在子会话关闭的时候自动删除。做一个形象的比喻。即现在做父亲的去叫儿子造一座房子。当儿子死亡的时候,这座房子也会消失。对于这种情况,数据库管理员需要注意。父会话只能够引用子会话从临时表中传递出来的数据。也就是说,父会话要访问子会话创建的临时表的数据,只有一种手段。即先让子会话对临时表中的数据进行查询或者操作,然后把结构回传给父会话。父会话是不能够直接访问子会话所创建的临时表。当然这个限制是专门针对本地临时表而言的。对于全局临时表来说,本身就是所有用户都可以访问,为此就没有这个限制。
全局临时表
以两个井号 (##) 开头的那些表名。在所有连接上都能看到全局临时表或者这样说只要这个全局临时表存在,那么用户创建会话后对所有的用户都是可见的。如果在创建全局临时表的连接断开前没有显式地除去这些表,那么只要所有其它任务停止引用它们,这些表即被除去。当创建全局临时表的连接断开后,新的任务不能再引用它们(换句话说旧的任务还何以引用)。当前的语句一执行完,任务与表之间的关联即被除去;因此通常情况下,只要创建全局临时表的连接断开,全局临时表即被除去。insert tablename
select * from tablename
可以创建本地和全局临时表。本地临时表仅在当前会话中可见;全局临时表在所有会话中都可见。本地临时表的名称前面有一个编号符 (#table_name),而全局临时表的名称前面有两个编号符 (##table_name)。SQL 语句使用 CREATE TABLE 语句中为 table_name 指定的名称引用临时表:CREATE TABLE #MyTempTable (cola INT PRIMARY KEY)
INSERT INTO #MyTempTable VALUES (1)如果本地临时表由存储过程创建或由多个用户同时执行的应用程序创建,则 SQL Server 必须能够区分由不同用户创建的表。为此,SQL Server 在内部为每个本地临时表的表名追加一个数字后缀。存储在 tempdb 数据库的 sysobjects 表中的临时表,其全名由 CREATE TABLE 语句中指定的表名和系统生成的数字后缀组成。为了允许追加后缀,为本地临时表指定的表名 table_name 不能超过 116 个字符。除非使用 DROP TABLE 语句显式除去临时表,否则临时表将在退出其作用域时由系统自动除去: 当存储过程完成时,将自动除去在存储过程中创建的本地临时表。由创建表的存储过程执行的所有嵌套存储过程都可以引用此表。但调用创建此表的存储过程的进程无法引用此表。
所有其它本地临时表在当前会话结束时自动除去。
全局临时表在创建此表的会话结束且其它任务停止对其引用时自动除去。任务与表之间的关联只在单个 Transact-SQL 语句的生存周期内保持。换言之,当创建全局临时表的会话结束时,最后一条引用此表的 Transact-SQL 语句完成后,将自动除去此表。
在存储过程或触发器中创建的本地临时表与在调用存储过程或触发器之前创建的同名临时表不同。如果查询引用临时表,而同时有两个同名的临时表,则不定义针对哪个表解析该查询。嵌套存储过程同样可以创建与调用它的存储过程所创建的临时表同名的临时表。嵌套存储过程中对表名的所有引用都被解释为是针对该嵌套过程所创建的表,例如:CREATE PROCEDURE Test2
AS
CREATE TABLE #t(x INT PRIMARY KEY)
INSERT INTO #t VALUES (2)
SELECT Test2Col = x FROM #t
GO
CREATE PROCEDURE Test1
AS
CREATE TABLE #t(x INT PRIMARY KEY)
INSERT INTO #t VALUES (1)
SELECT Test1Col = x FROM #t
EXEC Test2
GO
CREATE TABLE #t(x INT PRIMARY KEY)
INSERT INTO #t VALUES (99)
GO
EXEC Test1
GO下面是结果集:(1 row(s) affected)Test1Col
-----------
1 (1 row(s) affected)Test2Col
-----------
2 当创建本地或全局临时表时,CREATE TABLE 语法支持除 FOREIGN KEY 约束以外的其它所有约束定义。如果在临时表中指定 FOREIGN KEY 约束,该语句将返回警告信息,指出此约束已被忽略,表仍会创建,但不具有 FOREIGN KEY 约束。在 FOREIGN KEY 约束中不能引用临时表。考虑使用表变量而不使用临时表。当需要在临时表上显式地创建索引时,或多个存储过程或函数需要使用表值时,临时表很有用。通常,表变量提供更有效的查询处理。有关更多信息,请参见 table。
http://topic.csdn.net/u/20091111/14/ef883dff-b3e1-411b-b242-a43a21e84f24.html?16131
一个没有索引的视图其实只是一个虚拟表,没有任何物理的数据,它就是一段代码组成的东西,包含了描述它的元数据,如结构,依赖性等.
1.它可以对基础数据做些聚合之类的操作后提供使用.
2.它可以筛选数据,让客户只能访问视图以达到保护原表的目的.
3.同样,视图不能包含单独的ORDER BY .因为它被认为是一个表,表是逻辑实体,本身里面的数据时随便放的,并米有刻意按照某个顺序存储数据.说几点关于视图的东西1.视图中的ORDER BY
视图中的ORDER BY 绝非它本意--它不起排序的作用。
平时我们用 select top n * from tb order by col1 这里的order by 不仅排序还确定要返回哪几行
视图我们用 select top n * from tb order by col1 这里的ORDER BY 只能用来确定希望返回哪几行.
因为我们的视图最后出来的东西本质上是个表,这个时候你去查询这个视图的时候 出来的结果可不一定是按照COL1排序的
因为视图它就是个表 表是逻辑实体,本身里面的数据时随便放的.看实例:
create table k (a int , b int)
insert k select 1,2
insert k select 2,6
insert k select 3,7
insert k select 4,2
insert k select 5,9
gp
create view v_showk
as
select top 100 percent *
from k
order by b
go
select * from v_showk
/*
a b
----------- -----------
1 2
2 6
3 7
4 2
5 9
*/
-------结果并没有按照你期待的B排序 这就说明视图里的order by 是没有起到排序作用的----------------
2.视图刷新的问题 sp_refreshview
有时候你会发现当你修改基础表的结构后,视图并没有跟着变,解决的方法就是修改后立即进行视图的刷新.特别是你试图出现select *的时候
USE tempdb;
GO
IF OBJECT_ID('dbo.V1') IS NOT NULL
DROP VIEW dbo.V1;
GO
IF OBJECT_ID('dbo.T1') IS NOT NULL
DROP TABLE dbo.T1;
GO
CREATE TABLE dbo.T1(col1 INT, col2 INT);
INSERT INTO dbo.T1(col1, col2) VALUES(1, 2);
GO
--建立视图
CREATE VIEW dbo.V1
AS
SELECT * FROM dbo.T1;
GO
-- 查看视图
SELECT * FROM dbo.V1;
GO
/*
col1 col2
----------- -----------
1 2
*/
--修改表架构
ALTER TABLE dbo.T1 ADD col3 INT;
GO
--再次查看视图
SELECT * FROM dbo.V1;
GO
/*
col1 col2
----------- -----------
1 2
*/
--发现修改后的结构没有出现在眼前,刷新视图
EXEC sp_refreshview 'dbo.V1';
GO
--再次查看
SELECT * FROM dbo.V1;
GO
/*
col1 col2 col3
----------- ----------- -----------
1 2 NULL
*/
------------这里分享个一次刷新所有视图的代码(书上)-----------
--刷新所有视图
SELECT N'EXEC sp_refreshview '
+ QUOTENAME(VIEW_NAME, '''') + ';' AS cmd
FROM (SELECT QUOTENAME(TABLE_SCHEMA)
+ N'.' + QUOTENAME(TABLE_NAME) AS VIEW_NAME
FROM INFORMATION_SCHEMA.VIEWS) AS V
WHERE OBJECTPROPERTY(OBJECT_ID(VIEW_NAME), 'IsSchemaBound') = 0;
GO3.视图的模块化解题
如果一个题目解题思路写成一个语句比较长 比较难读 可以尝试用视图分开它 依次攻破 --(书上的例子,懒了下,盗用数据说明问题)
SET NOCOUNT ON;
USE tempdb;
GO
IF OBJECT_ID('dbo.Sales') IS NOT NULL
DROP TABLE dbo.Sales;
GO
CREATE TABLE dbo.Sales
(
mnth DATETIME NOT NULL PRIMARY KEY,
qty INT NOT NULL
);
INSERT INTO dbo.Sales(mnth, qty) VALUES('20041201', 100);
INSERT INTO dbo.Sales(mnth, qty) VALUES('20050101', 110);
INSERT INTO dbo.Sales(mnth, qty) VALUES('20050201', 120);
INSERT INTO dbo.Sales(mnth, qty) VALUES('20050301', 130);
INSERT INTO dbo.Sales(mnth, qty) VALUES('20050401', 140);
INSERT INTO dbo.Sales(mnth, qty) VALUES('20050501', 140);
INSERT INTO dbo.Sales(mnth, qty) VALUES('20050601', 130);
INSERT INTO dbo.Sales(mnth, qty) VALUES('20050701', 120);
INSERT INTO dbo.Sales(mnth, qty) VALUES('20050801', 110);
INSERT INTO dbo.Sales(mnth, qty) VALUES('20050901', 100);
INSERT INTO dbo.Sales(mnth, qty) VALUES('20051001', 110);
INSERT INTO dbo.Sales(mnth, qty) VALUES('20051101', 100);
INSERT INTO dbo.Sales(mnth, qty) VALUES('20051201', 120);
INSERT INTO dbo.Sales(mnth, qty) VALUES('20060101', 130);
INSERT INTO dbo.Sales(mnth, qty) VALUES('20060201', 140);
INSERT INTO dbo.Sales(mnth, qty) VALUES('20060301', 100);
INSERT INTO dbo.Sales(mnth, qty) VALUES('20060401', 100);
INSERT INTO dbo.Sales(mnth, qty) VALUES('20060501', 100);
INSERT INTO dbo.Sales(mnth, qty) VALUES('20060601', 110);
INSERT INTO dbo.Sales(mnth, qty) VALUES('20060701', 120);
INSERT INTO dbo.Sales(mnth, qty) VALUES('20060801', 110);
INSERT INTO dbo.Sales(mnth, qty) VALUES('20060901', 120);
INSERT INTO dbo.Sales(mnth, qty) VALUES('20061001', 130);
INSERT INTO dbo.Sales(mnth, qty) VALUES('20061101', 140);
INSERT INTO dbo.Sales(mnth, qty) VALUES('20061201', 100);
GO
-----目标结果-----根据本月于上个月差来判断销售趋势
/*
start_range end_range trend
----------- --------- -------
200412 200412 unknown
200501 200504 up
200505 200505 same
200506 200509 down
200510 200510 up
200511 200511 down
200512 200602 up
200603 200603 down
200604 200605 same
200606 200607 up
200608 200608 down
200609 200611 up
200612 200612 down
*/
--VSalesRN视图给每个月上编号
IF OBJECT_ID('dbo.VSalesRN') IS NOT NULL
DROP VIEW dbo.VSalesRN;
GO
CREATE VIEW dbo.VSalesRN
AS
SELECT mnth, qty, ROW_NUMBER() OVER(ORDER BY mnth) AS rn
FROM dbo.Sales;
GO
--VSgn视图利用sign函数和自连接,求出sgn标识趋势
IF OBJECT_ID('dbo.VSgn') IS NOT NULL
DROP VIEW dbo.VSgn;
GO
CREATE VIEW dbo.VSgn
AS
SELECT Cur.mnth, Cur.qty, isnull(SIGN(Cur.qty - Prv.qty),2) AS sgn
FROM dbo.VSalesRN AS Cur
left JOIN dbo.VSalesRN AS Prv
ON Cur.rn = Prv.rn + 1;
--VGrp视图根据对标识的分组,取出最后标定范围的分组因子grp
IF OBJECT_ID('dbo.VGrp') IS NOT NULL
DROP VIEW dbo.VGrp;
GO
create VIEW dbo.VGrp
AS
SELECT mnth, sgn,
DATEADD(month,
-ROW_NUMBER() OVER(PARTITION BY sgn ORDER BY mnth),
mnth) AS grp
FROM dbo.VSgn;
GO
--VTrends视图 根据sgn 和 grp分组 求出自己范围内的最大最小值 并且标识出对应的中文表示
IF OBJECT_ID('dbo.VTrends') IS NOT NULL
DROP VIEW dbo.VTrends;
GO
CREATE VIEW dbo.VTrends
AS
SELECT
CONVERT(VARCHAR(6), MIN(mnth), 112) AS start_range,
CONVERT(VARCHAR(6), MAX(mnth), 112) AS end_range,
CASE sgn
WHEN -1 THEN 'down'
WHEN 0 THEN 'same'
WHEN 1 THEN 'up'
ELSE 'unknown'
END AS trend
FROM dbo.VGrp
GROUP BY sgn, grp;
----------检索视图------------
SELECT start_range, end_range, trend
FROM dbo.VTrends
ORDER BY start_range;
5.视图的更新 update
视图不仅可以修改,而且可以更新.因为对它操作时会影响基础表的。
这里我就说一个注意点:当你的视图是由2个表链接查询出来的,而你做的操作是更新的时候,要注意了:会出现状况:
SET NOCOUNT ON;
USE tempdb;
GO
IF OBJECT_ID('dbo.VCustOrders') IS NOT NULL
DROP VIEW dbo.VCustOrders;
GO
IF OBJECT_ID('dbo.Orders') IS NOT NULL
DROP TABLE dbo.Orders;
GO
IF OBJECT_ID('dbo.Customers') IS NOT NULL
DROP TABLE dbo.Customers;
GO
---建Customers表
CREATE TABLE dbo.Customers
(
cid INT NOT NULL PRIMARY KEY,
cname VARCHAR(25) NOT NULL
)
INSERT INTO dbo.Customers(cid, cname) VALUES(1, 'Cust 1');
INSERT INTO dbo.Customers(cid, cname) VALUES(2, 'Cust 2');
---建Orders 表
CREATE TABLE dbo.Orders
(
oid INT NOT NULL PRIMARY KEY,
cid INT NOT NULL REFERENCES dbo.Customers
)
INSERT INTO dbo.Orders(oid, cid) VALUES(1001, 1);
INSERT INTO dbo.Orders(oid, cid) VALUES(1002, 1);
INSERT INTO dbo.Orders(oid, cid) VALUES(1003, 1);
INSERT INTO dbo.Orders(oid, cid) VALUES(2001, 2);
INSERT INTO dbo.Orders(oid, cid) VALUES(2002, 2);
INSERT INTO dbo.Orders(oid, cid) VALUES(2003, 2);
GO
-----创建视图VCustOrders 显示2表的链接内容
CREATE VIEW dbo.VCustOrders
AS
SELECT C.cid, C.cname, O.oid
FROM dbo.Customers AS C
JOIN dbo.Orders AS O
ON O.cid = C.cid;
GO
--显示数据
SELECT cid, cname, oid FROM dbo.VCustOrders;
GO
/*
cid cname oid
----------- ------------------------- -----------
1 Cust 1 1001
1 Cust 1 1002
1 Cust 1 1003
2 Cust 2 2001
2 Cust 2 2002
2 Cust 2 2003
*/
--更新:我们想把订单号为1001的那个公司名cname 改个名字,初期是只想改这么个订单(这是本来想做的)
UPDATE dbo.VCustOrders
SET cname = 'Cust 42'
WHERE oid = 1001;
GO
--再次查询视图
SELECT cid, cname, oid FROM dbo.VCustOrders;
GO
/*
cid cname oid
----------- ------------------------- -----------
1 Cust 42 1001
1 Cust 42 1002
1 Cust 42 1003
2 Cust 2 2001
2 Cust 2 2002
2 Cust 2 2003
*/
------其实这里很好理解,修改的是表Customers 而不是视图 所以改了再查视图 视图又是从表那边链接过来 当然三个就一起变了----
可以 insert into #tt select xxx from a表 join b表 on .... where...这样可以从不同表里选数据来插入。