SQL TEMP表:临时在存储过程中创建表
如果您以前使用过SQL Server,那么您可能知道物理表的概念。您可以创建一个列表来存储数据,并使用这个表来查询存储过程中的特定信息。SQL Server还提供了一种创建临时表的方法。这些临时表的创建方式是相同的,但需要动态地创建和销毁它们。当需要循环遍历数据(比如使用游标)或需要从较大的记录集中删除重复记录时,这些临时表非常有用。
SQL Server编程新手?在Udemy.com了解如何创建查询、报告和存储过程。
如何设计表格
在创建临时表之前,您应该首先知道如何设计表是临时或永久的。SQL表由列组成。每个记录都是一行。SQL表是一个更复杂和有用的常用电子表格形式。电子表格是比较表格结果集的好方法,即使它在技术上是不准确的。但是,它将有助于您了解行和列的概念。
在设计物理表时,应该在设计临时表时使用相同的概念。即使临时表是动态创建的,您仍然应该考虑列数据类型和索引,以加快查询速度,并确保正确的数据存储在临时表中。
由于使用相同的“Create Table”作为其他表创建了Temp表,因此您需要考虑将存储在表中的数据。您还应在创建表时设置主键,如果您计划经常使用存储的过程或查询,请使用索引。
使用CREATE表程序创建TEMP表
大多数SQL Server表设计器都与SQL Server Management Studio一起工作,该Studio允许您使用可视化工具来创建表。但是,如果您想在过程中或使用代码中创建表,则需要创建表命令。实际上,Management Studio中的Visual Tool使用Create Table命令,但它只是屏蔽从视图中更复杂的命令,并使您更轻松地创建表。
要向SQL引擎表明您需要一个临时表,可以使用“#”字符。在任何唯一的表名前面使用此字符将创建一个临时表,您可以在存储过程的生命周期中使用它。
以下代码是一个客户临时表的CREATE TABLE命令示例:
CREATE TABLE #Customer_Temp (CustomerId int NOT NULL, FirstName varchar(50), LastName varchar(50))
在上面的代码中,创建了一个名为“Customer_Temp”的临时表。有三列:客户id,以及名和姓。第一列是一个整数,接下来的两列允许您存储字符串。
此时,只创建了表结构。大多数临时表用于对其他表的数据进行操作。例如,您可能希望在一个客户表中标识多个客户帐户。您可以检索重复的帐户并将它们存储在一个临时表中。然后,临时表将允许您计算表中有多少重复值。您可以只使用计数,甚至标记原始客户表中的重复帐户。
下面的代码根据客户的姓氏获取重复客户帐户的列表:
insert into #customer_temp (firstname, lastname, customerId) select firstname, lastname, customerId from customer group by firstname, lastname, customerId having (count(lastname) > 1)
当然,大多数业务逻辑需要另一列来检测重复记录,因为可以有多个客户具有相同的姓氏。然而,这只是一个帮助您理解临时表和查找重复记录的简单示例。
在上面的代码中,任何基于具有相同姓氏的记录而拥有重复记录的客户都会被插入临时表。您可以假设customerId列只允许唯一的记录,因此您可以使用该列从主客户表获得唯一的Id。
这个查询可能会产生数千条记录,所以如果您计划在表之间进行任何链接,那么应该在临时表上设置主键和索引,以加快查询速度。这是使用ALTER TABLE短语完成的。
使用ALTER Table命令改变表的结构
如果您使用SQL创建表,那么您应该熟悉ALTER TABLE命令,因为它会在您已经创建了表之后更改表结构。在上面的CREATE TABLE命令中,创建了表结构,它是一个可用的结构,但如果您有数千条记录,并且需要链接到数据库中的其他表,那么如果您没有索引或主键,它会极大地影响性能。您可以在SQL临时表上动态创建这两个组件。
首先,您在必须是唯一的列上创建主键。在包含动态插入的记录的温度表上,这可能很困难。上面使用的查询使用逻辑,即插入的记录应该是唯一的,但如果您尝试在具有相同记录值的临时表上制作主键时,SQL将抛出错误。因此,当您动态创建主键时,应确保您的TEMP表仅具有主键列的唯一值。
以下代码在CustomerId列上创建一个主键:
alter table #customer_temp添加主键(CustomerID)
很简单。在Customer_Temp表上调用ALTER TABLE,并在CustomerId列上添加主键。同样,如果在CustomerId列中有任何重复的值,则ALTER TABLE语句将失败。此外,主键不能包含NULL值。如果您注意到在CREATE TABLE语句中,列上有“not null”规范,那么在本例中,当您试图在设置主键之前插入任何空值时,将会得到一个错误。但是,如果你没有在临时表的create语句中指定NOT NULL,然后试图在同一列上创建一个主键,如果存在NULL值,SQL将返回一个错误。
使用Create Index在Temp表上创建索引
如果您只在Temp表的主键上执行一些查询,那么您可能不需要额外的索引。主键是群集索引,因此在您的表上创建一个会自动设置将加快临时表查询的索引。
假设您希望将临时表的姓氏列链接到主客户表的姓氏列。这将大大降低查询的速度,因为临时表在姓氏列上没有索引。因此,您可能希望在姓氏列上设置索引。
以下代码在Temp表中的姓氏列上创建索引:
在#ceamer_temp(lastname)上创建index tempcustomerIndex
上面的代码在临时表的LastName列上创建了一个非惟一索引。非惟一索引允许列中出现空值和相同的值。还可以在INDEX关键字前使用UNIQUE关键字来指定列的值必须是唯一的。但是,您必须再次确保列中的值是惟一的,否则SQL语句将失败并给出错误。
查询SQL Server Temp表的结果
设置好临时表后,现在可以对其执行查询。临时表的查询结构与常规表相同。例如,要从临时客户表中获取记录列表,可以使用以下查询示例:
select * from #Customer_Temp order by LastName
上面的语句获取插入到临时表中的所有记录,并按姓氏列对其排序。
您可能希望验证您检索了所有正确的记录,并且您的临时表包含了正确的数据。大多数重要的查询都需要抽样一些数据来验证准确性。在这个示例中,您可以将客户Id列链接在一起。然后,您将验证临时表中的客户Id和信息是否与主客户表中的信息相同。它确保您编辑正确的记录。例如,下面的代码链接了临时表和主表,并显示了一个数据集,您可以使用该数据集来对数据进行抽样以获得准确性:
select * from #Customer_Temp ctemp join客户c on ctempCustomerId = c.CustomerId order by c.LastName
在上面的语句中,两个表是链接的,但是请注意使用了别名。这些表使用“ctemp”和“c”作为别名。ctemp别名指向临时表,c别名指向主客户表。这两个表都有相同的列,因此需要为它们取别名,以便在“where”子句中使用它们。在这个查询中没有where子句,但是有一个“order by”子句,因此您需要指定是使用临时表的姓氏列还是主Customer表的列。在这个例子中,“c。“LastName”指的是Customer表的姓氏列。
您还可以基于这两个表更新记录。例如,假设您希望为主客户表中的每条记录更新一个“重复”列,在主客户表中,它作为重复被复制到临时表中。因为我们的临时表包含一个发现是重复的客户列表,所以您可以使用这个表数据准确地更新主客户表。
以下代码基于临时表数据更新客户表:
update customer set duplicate = 1 where customerId in (select customerId in #Customer_Temp)
在上面的查询中,假设客户表具有采用整数或一位的“复制”列。在这个例子中,“1”是“真实”。因为我们想知道客户是一份重复的,原始插入查询仅插入了表中出现的客户,而不是基于姓氏而出现在表中。通常,您将使用其他一些因素,例如社会安全号码,电话号码或电子邮件地址。此示例使用姓氏以简便,但您可能有多个客户姓氏的客户。
上述查询的业务逻辑是“如果客户存在于包含重复记录id的临时表中,那么将主客户标记为重复记录”。如果临时表包含数千条记录,则此查询可能会使生产数据库变得缓慢。但是,建立了索引和主键后,查询不应该长时间运行,也不应该中断常规生产,比如前端数据库或内部客户服务应用程序。
本文仅包含如何使用临时表的示例,如何创建一个以及如何更改它以加快查询。使用重复记录和标志的示例是使用企业数据库SQL Server时可能会遇到的内容。重复的记录可能导致数据完整性问题,因此您可能需要识别重复记录以帮助简化系统。
在您在生产数据上运行更新语句之前,请始终如此小心。始终首先对数据进行采样,并仅在您确定更新查询准确时运行查询。在运行查询之前,您应该备份数据库表,以防您需要回滚任何更改。如果出现任何错误,则可以在更新查询之前将数据传输到原件,因此不会发生数据损坏。