[MSSQL]表变量和临时表的区别

MSSQL表变量与临时表详解
本文详细对比了MSSQL中的表变量和临时表的特性,包括作用域、使用场景、创建方式、列类型、索引、约束、DDL操作、数据插入方式、析构方式、事务处理、存储过程重编译、回滚影响、统计数据、作为参数传入存储过程、显式命名对象、动态SQL中的使用等。并通过实验展示了在不同情况下的性能差异。

一、表变量

  表变量在SQL Server 2000中首次被引入。表变量的具体定义包括列定义,列名,数据类型和约束。而在表变量中可以使用的约束包括主键约束,唯一约束,NULL约束和CHECK约束(外键约束不能在表变量中使用)。定义表变量的语句是和正常使用Create Table定义表语句的子集。只是表变量通过DECLARE @local_variable语句进行定义。

  表变量的特征:

表变量拥有特定作用域(在当前批处理语句中,但不在任何当前批处理语句调用的存储过程和函数中), 表变量在批处理结束后自动被清除。 表变量较临时表产生更少的存储过程重编译。 针对表变量的事务仅仅在更新数据时生效,所以锁和日志产生的数量会更少。 由于表变量的作用域如此之小,而且不属于数据库的持久部分,所以事务回滚不会影响表变量。

  表变量可以在其作用域内像正常的表一样使用。更确切的说,表变量可以被当成正常的表或者表表达式一样在SELECT,DELETE,UPDATE,INSERT语句中使用,但是表变量不能在类似"SELECT select_list INTO table_variable"这样的语句中使用。而在SQL Server2000中,表变量也不能用于INSERT INTO table_variable EXEC stored_procedure这样的语句中。

  表变量不能做如下事情:

虽然表变量是一个变量,但是其不能赋值给另一个变量。 check约束,默认值和计算列不能引用自定义函数。 不能为约束命名。 不能Truncate表变量。 不能向标识列中插入显式值(也就是说表变量不支持SET IDENTITY_INSERT ON)

  下面来玩玩表变量吧。

  定义一个表变量,插入一条数据,然后查询:

复制代码
  DECLARE @tb1 Table
  (
   Id int,
   Name varchar(20),
   Age int
  )

  INSERT INTO @tb1 VALUES(1,'刘备',22)

  SELECT * FROM @tb1
复制代码

  输出结果如下:

  

  再来试试一些不符合要求的情况,例如添加表变量后,添加约束,并对约束命名:

  ALTER TABLE @tb1
    ADD CONSTRAINT CN_AccountAge
    CHECK 
    (Account_Age > 18);    -- 插入年龄必须大于18

  SQL Server提示错误如下:

  

  SQL Server不支持定义表变量时对Constraint命名,也不支持定义表变量后,对其建Constraint。

  更多的不允许,请查看上面的要求。

二、临时表

  在深入临时表之前,我们要了解一下会话(Session),一个会话仅仅是一个客户端到数据引擎的连接。在SQL Server Management Studio中,每一个查询窗口都会和数据库引擎建立连接。一个应用程序可以和数据库建立一个或多个连接,除此之外,应用程序还可能建立连接后一直不释放知道应用程序结束,也可能使用完释放连接需要时建立连接。

  临时表和Create Table语句创建的表有着相同的物理工程,但临时表与正常的表不同之处有:

  1、临时表的名称不能超过116个字符,这是由于数据库引擎为了辨别不同会话建立不同的临时表,所以会自动在临时表的名字后附加一串。

  2、局部临时表(以"#"开头命名的)作用域仅仅在当前的连接内,从在存储过程中建立局部临时表的角度来看,局部临时表会在下列情况下被Drop:
    a、显示调用Drop Table语句
    b、当局部临时表在存储过程内被创建时,存储过程结束也就意味着局部临时表被Drop。
    c、当前会话结束,在会话内创建的所有局部临时表都会被Drop。

  3、全局临时表(以"##"开头命名的)在所有的会话内可见,所以在创建全局临时表之前首先检查其是否存在,否则如果已经存在,你将会得到重复创建对象的错误。
    a、全局临时表会在创建其的会话结束后被Drop,Drop后其他会话将不能对全局临时表进行引用。
    b、引用是在语句级别进行,如:
      1.新建查询窗口,运行语句:

  CREATE TABLE ##temp(RowID int)
  INSERT INTO ##temp VALUES(3)
 
 
 

--创建局部临时表
create table #tmpStudent(Tid int,Name varchar(50),Age int)
insert into #tmpStudent values('xiaowang',25)

select * from #tmpStudent

--创建局部临时表 另一种写法
select * into #tmpStudent from student
select * from #tmpStudent

 

--另一种创建方法:

create table tempdb.MyTempTable(Tid int) --有对应权限才可以这么写

 

--删除

drop table #tmpStudent

      2.再次新建一个查询窗口,每5秒引用一次全局临时表

  While 1=1 
  BEGIN
  SELECT * FROM ##temp
  WAITFOR delay '00:00:05'
  END

      3.回到第一个窗口,关闭窗口。
      4.下一次第二个窗口引用时,将产生错误。

 

  4、不能对临时表进行分区。

  5、不能对临时表加外键约束。

  6、临时表内列的数据类型不能定义成没有在TempDb中没有定义自定义数据类型(自定义数据类型是数据库级别的对象,而临时表属于TempDb)。由于TempDb在每次SQL Server重启后会被自动创建,所以你必须使用startup stored procedure来为TempDb创建自定义数据类型。你也可以通过修改Model数据库来达到这一目标。

  7、XML列不能定义成XML集合的形式,除非这个集合已经在TempDb中定义。

  临时表既可以通过Create Table语句创建,也可以通过"SELECT <select_list> INTO #table"语句创建。你还可以针对临时表用"INSERT INTO #table EXEC stored_procedure"这样的语句。
  临时表可以拥有命名的约束和索引。但是,当两个用户在同一时间调用同一存储过程时,将会产生”There is already an object named ‘<objectname>’ in the database”这样的错误。所以最好的做法是不用为建立的对象进行命名,而使用系统分配的在TempDb中唯一的。

三、误区

  误区1.表变量仅仅在内存中。

  误区2.临时表仅仅存储在物理介质中。

  这两种观点都是错误的,只有内存足够,表变量和临时表都会在内存中创建和处理。他们也同样可以在任何时间被存入磁盘。

  注意表变量的名字是系统分配的,表变量的第一个字符”@”并不是一个字母,所以它并不是一个有效的变量名。系统会在TempDb中为表变量创建一个系统分配的名称,所以任何在sysobjects或sys.tables查找表变量的方法都会失败。

  正确的方法应该是我前面例子中的方法,我看到很多人使用如下查询查表变量:

  select * from sysobjects where name like'#tempTables%'

  上述代码看上去貌似很好用,但会产生多用户的问题。你建立两个连接,在第一个连接中创建临时表,在第二个窗口中运行上面的语句能看到第一个连接创建的临时表,如果你在第二个连接中尝试操作这个临时表,那么可能会产生错误,因为这个临时表不属于你的会话。

  误区3.表变量不能拥有索引。

    这个误区也同样错误。虽然一旦你创建一个表变量之后,就不能对其进行DDL语句了,这包括Create Index语句。然而你可以在表变量定义的时候为其创建索引)比如如下语句。

  declare @MyTableVariable table (RowID intPRIMARY KEY CLUSTERED) 

    这个语句将会创建一个拥有聚集索引的表变量。由于主键有了对应的聚集索引,所以一个系统命名的索引将会被创建在RowID列上。

    下面的例子演示你可以在一个表变量的列上创建唯一约束以及如何建立复合索引。

   declare @temp TABLE (
     RowID int NOT NULL,
     ColA int NOT NULL,
     ColB char(1)UNIQUE,
     PRIMARY KEY CLUSTERED(RowID, ColA))

  1) SQL 并不能为表变量建立统计信息,就像其能为临时表建立统计信息一样。这意味着对于表变量,执行引擎认为其只有1行,这也意味着针对表变量的执行计划并不是最优。虽然估计的执行计划对于表变量和临时表都为1,但是实际的执行计划对于临时表会根据每次存储过程的重编译而改变。如果临时表不存在,在生成执行计划的时候会产生错误。

  2) 一旦建立表变量后就无法对其进行DDL语句操作。因此如果需要为表建立索引或者加一列,你需要临时表。

  3) 表变量不能使用select …into语句,而临时表可以。

  4) 在SQL Server 2008中,你可以将表变量作为参数传入存储过程。但是临时表不行。在SQL Server 2000和2005中表变量也不行。

  5) 作用域:表变量仅仅在当前的批处理中有效,并且对任何在其中嵌套的存储过程等不可见。局部临时表只在当前会话中有效,这也包括嵌套的存储过程。但对父存储过程不可见。全局临时表可以在任何会话中可见,但是会随着创建其的会话终止而DROP,其它会话这时就不能再引用全局临时表。

  6) 排序规则:表变量使用当前数据库的排序规则,临时表使用TempDb的排序规则。如果它们不兼容,你还需要在查询或者表定义中进行指定。

  7) 你如果希望在动态SQL中使用表变量,你必须在动态SQL中定义表变量。而临时表可以提前定义,在动态SQL中进行引用。

四、如何选择

  微软推荐使用表变量,如果表中的行数非常小,则使用表变量。很多”网络专家”会告诉你100是一个分界线,因为这是统计信息创建查询计划效率高低的开始。但是我还是希望告诉你针对你的特定需求对临时表和表变量进行测试。很多人在自定义函数中使用表变量,如果你需要在表变量中使用主键和唯一索引,你会发现包含数千行的表变量也依然性能卓越。但如果你需要将表变量和其它表进行join,你会发现由于不精准的执行计划,性能往往会非常差。

  为了证明这点,请看本文的附件。附件中代码创建了表变量和临时表.并装入了AdventureWorks数据库的Sales.SalesOrderDetail表。为了得到足够的测试数据,我将这个表中的数据插入了10遍。然后以ModifiedDate 列作为条件将临时表和表变量与原始的Sales.SalesOrderDetail表进行了Join操作,从统计信息来看IO差别显著。从时间来看表变量做join花了50多秒,而临时表仅仅花了8秒。

  如果你需要在表建立后对表进行DLL操作,那么选择临时表吧。

  临时表和表变量有很多类似的地方。所以有时候并没有具体的细则规定如何选择哪一个。对任何特定的情况,你都需要考虑其各自优缺点并做一些性能测试。下面的表格会让你比较其优略有了更详细的参考。

五、总结

特性表变量临时表
作用域当前批处理当前会话,嵌套存储过程,全局:所有会话
使用场景自定义函数,存储过程,批处理自定义函数,存储过程,批处理
创建方式DECLARE statement only.只能通过DECLEARE语句创建

CREATE TABLE 语句

SELECT INTO 语句.

表名长度最多128字节最多116字节
列类型

可以使用自定义数据类型

可以使用XML集合

自定义数据类型和XML集合必须在TempDb内定义
Collation字符串排序规则继承自当前数据库字符串排序规则继承自TempDb数据库
索引索引必须在表定义时建立索引可以在表创建后建立
约束PRIMARY KEY, UNIQUE, NULL, CHECK约束可以使用,但必须在表建立时声明PRIMARY KEY, UNIQUE, NULL, CHECK. 约束可以使用,可以在任何时后添加,但不能有外键约束
表建立后使用DDL (索引,列)不允许允许.
数据插入方式INSERT 语句 (SQL 2000: 不能使用INSERT/EXEC).

INSERT 语句, 包括 INSERT/EXEC.

SELECT INTO 语句.

Insert explicit values into identity columns (SET IDENTITY_INSERT).不支持SET IDENTITY_INSERT语句支持SET IDENTITY_INSERT语句
Truncate table不允许允许
析构方式批处理结束后自动析构显式调用 DROP TABLE 语句.
当前会话结束自动析构 (全局临时表: 还包括当其它会话语句不在引用表.)
事务只会在更新表的时候有事务,持续时间比临时表短正常的事务长度,比表变量长
存储过程重编译会导致重编译
回滚不会被回滚影响会被回滚影响
统计数据不创建统计数据,所以所有的估计行数都为1,所以生成执行计划会不精准创建统计数据,通过实际的行数生成执行计划。
作为参数传入存储过程仅仅在SQL Server2008, 并且必须预定义 user-defined table type.不允许
显式命名对象 (索引, 约束).不允许允许,但是要注意多用户的问题
动态SQL必须在动态SQL中定义表变量可以在调用动态SQL之前定义临时表

 

posted on 2017-03-05 16:20  v.e.n.u.s 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/jx270/p/6505805.html

<think>我们有一个需求:在MSSQL中,使用变量存储名,然后执行SELECT *查询,并将结果集保存起来(可能是临时表变量等)。 根据引用[1]:我们可以使用动态SQL构建查询字符串,然后执行它。但是动态SQL的结果如何保存呢? 引用[2]展示了在存储过程中使用变量来存储SELECT的结果集。 引用[3]展示了一个函数返回类型,这也可以用来返回结果集。 引用[4]则说明了在变量赋值时使用SETSELECT的区别,但这里我们关注的是结果集。 因此,我们可以考虑以下方法: 1. 使用动态SQL将结果插入到临时表变量中。 2. 使用存储过程返回结果集(但如何将结果集保存到变量中?实际上,存储过程返回的结果集可以直接给客户端,但如果在批处理中想要保存,可能需要插入到变量临时表中)。 具体步骤: 方法1:使用动态SQL临时表(或变量) - 先声明一个变量(或者创建临时表)来存储结果。 - 然后构建动态SQL,将查询结果插入到这个变量/临时表中。 方法2:使用存储过程(如果需要复用,但这里我们只是动态名查询,可能不需要存储过程) 然而,由于名是动态的,我们无法在静态SQL中直接写INSERT INTO 变量 SELECT * FROM 动态名。所以必须使用动态SQL。 因此,我们采用方法1:使用动态SQL插入到变量中。 步骤: 1. 声明一个变量,其结构要与目标(动态名)的结构一致。但是,由于名是动态的,我们无法预先知道结构怎么办? 2. 或者,我们可以使用一个临时表,然后在动态SQL中创建临时表并插入数据?但这样临时表的作用域可能会出问题(动态SQL中创建的临时表在动态SQL执行完毕后会被删除)。 所以,我们可以在动态SQL外部创建临时表,但需要先知道结构。 解决动态结构问题: 我们可以利用SELECT * INTO #临时表 FROM 名,但这里名是变量,所以必须在动态SQL中执行。而且,我们可以在动态SQL中创建临时表,但这样创建的临时表在动态SQL执行完毕后依然存在(因为临时表以#开头,在当前会话中有效,只要创建它的批处理没有结束,后续就可以访问。但注意,动态SQL外部属于同一个会话,所以可以访问)。 因此,我们可以这样做: - 构建动态SQL:'SELECT * INTO #TempTable FROM ' + @TableName - 然后执行该动态SQL,这样就会创建临时表#TempTable并插入数据。 - 然后我们就可以在外面使用#TempTable了。 但是,这种方法要求我们事先不知道结构,而且每次执行都会创建新的临时表(如果已存在同名的临时表,会报错)。所以我们可以先判断临时表是否存在,如果存在则删除。 另一种方法是使用变量,但是变量需要预先定义结构,而动态的结构未知,所以不适合。 因此,我们选择临时表方法。 示例代码如下: ```sql DECLARE @TableName NVARCHAR(100) = 'YourTableName'; -- 替换为实际的名 DECLARE @Sql NVARCHAR(MAX); -- 如果临时表已存在,则删除 IF OBJECT_ID('tempdb..#TempTable') IS NOT NULL DROP TABLE #TempTable; -- 构建动态SQL:将动态的数据插入到临时表 SET @Sql = 'SELECT * INTO #TempTable FROM ' + QUOTENAME(@TableName); EXEC sp_executesql @Sql; -- 然后就可以使用临时表#TempTable了 SELECT * FROM #TempTable; ``` 注意:使用QUOTENAME()函数来处理名,防止SQL注入。 但是,这种方法有一个缺点:临时表的结构是在运行时确定的,所以在编写后续使用#TempTable的代码时,我们必须知道它的结构。如果我们需要在不同的上执行,那么后续代码可能需要动态编写(比如列名不确定)。 如果我们希望将结果集保存到一个变量中,注意结果集是一个集合,无法直接赋值给一个变量(除非是单值)。所以通常我们使用变量临时表来存储。 如果我们希望将结果集保存到变量中,并且结构是已知的(或者我们能够预先定义),那么我们可以使用以下方法: ```sql DECLARE @TableName NVARCHAR(100) = 'YourTableName'; DECLARE @Sql NVARCHAR(MAX); -- 假设我们已知结构,例如我们有一个变量@Results,其结构与目标相同 DECLARE @Results TABLE ( -- 这里需要定义目标一样的列 ID INT, Column1 VARCHAR(50), ... ); -- 构建动态SQL,将数据插入到变量 SET @Sql = 'INSERT INTO @Results SELECT * FROM ' + QUOTENAME(@TableName); -- 但这样会出错,因为动态SQL中无法访问外部定义的变量(作用域问题) -- 所以正确的方法是:使用临时表作为中间步骤,然后插入变量?或者不使用变量,直接使用临时表即可。 -- 因此,如果我们无法预先知道结构,那么使用临时表是更好的选择。 ``` 综上所述,如果我们不知道动态的结构,那么使用SELECT INTO创建临时表是最方便的。如果知道结构,我们可以预先定义变量,然后在动态SQL中插入,但这样需要处理作用域问题(动态SQL不能直接访问外部的变量)。我们可以通过将变量改为临时表(以#开头的)来解决,因为临时表在当前会话中全局可见。 所以,如果我们希望使用变量(或者我们想避免临时表,因为临时表在会话结束后才删除,而变量在批处理结束后就释放了),我们可以这样做: 1. 创建一个临时表(在动态SQL中创建,同时插入数据,然后外部访问这个临时表)。 2. 如果后续需要多次使用,且希望用变量,那么我们可以将临时表的数据复制到变量(但需要预先知道结构)。 因此,步骤: a) 使用动态SQL创建临时表(SELECT INTO #TempTable) b) 然后,如果我们想用变量,那么先声明一个相同结构的变量(需要知道结构),然后从临时表插入到变量。 但是,如果不知道结构,那么我们就只能一直使用临时表了。 所以,根据需求,如果我们只是临时使用,那么使用临时表即可。 总结:在不知道动态结构的情况下,使用动态SQL创建临时表(SELECT INTO #TempTable)是最简单的方法。 另外,如果我们希望将结果集返回给调用者(例如在存储过程中),我们可以直接使用临时表,或者使用输出参数返回结果集(存储过程可以通过值参数返回,但比较复杂)。 因此,针对问题“使用变量执行select *查询并保存结果集”,我们推荐使用临时表方法。 示例代码: ```sql DECLARE @TableName NVARCHAR(100) = 'tbl_mail_info'; -- 假设名 DECLARE @Sql NVARCHAR(MAX); -- 如果临时表已存在则删除 IF OBJECT_ID('tempdb..#TempResults') IS NOT NULL DROP TABLE #TempResults; -- 构建动态SQL,将查询结果保存到临时表 SET @Sql = N'SELECT * INTO #TempResults FROM ' + QUOTENAME(@TableName) + N';'; EXEC sp_executesql @Sql; -- 现在可以查询临时表 SELECT * FROM #TempResults; ``` 注意:临时表#TempResults在同一个会话/批处理中都可以使用,直到会话结束或显示删除。 另外,如果我们需要在动态SQL中执行更复杂的操作(比如多连接等),这个方法也适用。 但请注意,动态SQL中使用SELECT INTO创建临时表,这个临时表在动态SQL执行完毕后仍然存在,可以被之后的SQL语句使用。 如果我们需要多次使用同一个临时表结构,可以预先创建临时表(使用CREATE TABLE),然后在动态SQL中插入数据,而不是使用SELECT INTO(因为SELECT INTO会创建,如果已存在则报错)。 例如,我们可以先创建临时表(需要知道结构),然后动态插入数据: ```sql -- 假设我们预先知道结构 CREATE TABLE #TempResults ( mail_type NVARCHAR(50), mail_subject NVARCHAR(100), mail_body NVARCHAR(MAX) ); DECLARE @TableName NVARCHAR(100) = 'tbl_mail_info'; DECLARE @Sql NVARCHAR(MAX) = N'INSERT INTO #TempResults SELECT * FROM ' + QUOTENAME(@TableName); EXEC sp_executesql @Sql; SELECT * FROM #TempResults; ``` 但是,如果不知道结构,就无法预先创建临时表。因此,我们推荐使用SELECT INTO动态创建临时表。 最后,如果我们需要将结果集传递给调用者(例如在存储过程中),那么我们可以直接返回结果集(通过SELECT语句),这样调用者就能收到结果集。在存储过程中使用动态SQL返回结果集也是可行的。 在存储过程中的示例: ```sql CREATE PROCEDURE GetTableData @TableName NVARCHAR(100) AS BEGIN DECLARE @Sql NVARCHAR(MAX); SET @Sql = N'SELECT * FROM ' + QUOTENAME(@TableName); EXEC sp_executesql @Sql; END ``` 调用这个存储过程就会返回对应的所有数据。但如果需要将结果集保存到变量中,则不行(因为结果集是多个行)。在调用存储过程时,客户端可以接收结果集,但在SQL Server内部,我们无法将存储过程返回的结果集直接赋值给变量。如果需要在内部处理,那么还是需要插入到临时表变量中。 因此,根据实际需求选择方法。 综上所述,对于在批处理中动态名查询并保存结果集,我们使用动态SQL创建临时表的方法。 </think>### 在 MSSQL 中使用变量执行 SELECT * 查询并保存结果集的方法 在 MSSQL 中使用变量执行动态查询并保存结果集,核心方法是**通过动态 SQL 结合临时表变量**实现。以下是详细步骤示例: --- ### 方法 1:使用动态 SQL 全局临时表(推荐) ```sql DECLARE @TableName NVARCHAR(100) = 'YourTableName'; -- 替换为实际名 DECLARE @Sql NVARCHAR(MAX); -- 创建全局临时表存储结果(以##开头,会话间共享) SET @Sql = N' SELECT * INTO ##TempResult FROM ' + QUOTENAME(@TableName) + '; '; EXEC sp_executesql @Sql; -- 使用结果集 SELECT * FROM ##TempResult; -- 清理临时表(可选) DROP TABLE IF EXISTS ##TempResult; ``` **说明** 1. 使用 `QUOTENAME()` 防止 SQL 注入 2. `SELECT INTO` 自动创建临时表并插入数据 3. 全局临时表 `##TempResult` 可在当前会话后续操作中访问[^1][^2] --- ### 方法 2:使用变量 + OPENROWSET(需开启 Ad Hoc Queries) ```sql DECLARE @TableName NVARCHAR(100) = 'YourTableName'; DECLARE @Sql NVARCHAR(MAX); DECLARE @Results TABLE (ID INT, Col1 NVARCHAR(50), ...); -- 需预定义列结构 SET @Sql = N' INSERT INTO @Results EXEC (''SELECT * FROM ' + @TableName + ''') '; EXEC sp_executesql @Sql, N'@Results TABLE(ID INT, Col1 NVARCHAR(50), ...) OUTPUT', @Results OUTPUT; SELECT * FROM @Results; -- 查看结果 ``` **注意** 需预先知道结构,且需启用配置: ```sql EXEC sp_configure 'Ad Hoc Distributed Queries', 1; RECONFIGURE; ``` --- ### 方法 3:存储过程封装结果集 ```sql CREATE PROCEDURE GetTableData @TableName NVARCHAR(100) AS BEGIN DECLARE @Sql NVARCHAR(MAX) = N'SELECT * FROM ' + QUOTENAME(@TableName); EXEC sp_executesql @Sql; END -- 调用存储过程保存结果 INSERT INTO #YourTempTable EXEC GetTableData @TableName = 'YourTable'; ``` **优点** 可复用逻辑,直接返回结果集[^2] --- ### 关键注意事项 1. **作用域问题** - 局部临时表 (`#Temp`) 仅在当前会话可见 - 全局临时表 (`##Temp`) 跨会话共享 - 变量 (`@TableVar`) 仅限当前批处理[^4] 2. **动态 SQL 安全** 务必使用 `QUOTENAME()` 处理名,避免 SQL 注入: ```sql SET @Sql = N'SELECT * FROM ' + QUOTENAME(@TableName); ``` 3. **结果集处理** ```sql -- 示例:将结果存入新 SELECT * INTO NewPermTable FROM ##TempResult; ``` --- ### 性能对比 | 方法 | 适用场景 | 性能影响 | |---------------------|-----------------------------------|---------------| | 全局临时表 (##Temp) | 大数据量+跨批处理操作 | 中等(需显式清理) | | 变量 (@Var) | 小数据量+已知结构 | 最低 | | 存储过程 | 需重复调用 | 高(首次编译慢) | > **推荐场景**:对未知结构的使用全局临时表;对已知结构的用预定义变量[^3][^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值