【问题标题】:Create Table and Insert Into using Stored Procedure使用存储过程创建表并插入
【发布时间】:2023-04-03 14:10:02
【问题描述】:

我有一个存储过程,我已将其安排为每晚午夜运行的作业。我希望存储过程在运行时将数据插入表中。我必须先创建表还是有办法在存储过程运行时创建表?我的第二个问题是:然后我需要一份工作来在每晚 11 点清除同一张表,然后在午夜再次运行存储过程。感谢您提供任何帮助。我很感激。

这是我的存储过程:

我已经创建了它运行成功的存储过程。我曾尝试使用 CREATE 和 INSERT INTO 但似乎都不起作用。

USE [TMWSUITE]
GO
/****** Object:  StoredProcedure [dbo].[Wynne_DriverSnapshot] Script Date: 10/22/2019 6:35:18 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER procedure [dbo].[Wynne_DriverSnapshot] as

WITH cte (mpp_id, mpp_firstname, mpp_lastname, mpp_status, mpp_fleet, mpp_terminal) as 
(
  Select mpp_id, mpp_firstname, mpp_lastname, mpp_status, mpp_fleet, mpp_terminal from manpowerprofile where mpp_terminationdt >= GETDATE()),
  cte2 (lgh_number, lgh_startdate, lgh_enddate, lgh_outstatus, rn, lgh_driver1, lgh_class, lgh_class2) as 
(
  Select lgh_number, lgh_startdate, lgh_enddate, lgh_outstatus, ROW_NUMBER() OVER (PARTITION by lgh_driver1 order by lgh_number desc) as 
  rn, lgh_driver1, lgh_class1, lgh_class2 From legheader
) 
  Select mpp_id, mpp_firstname, mpp_lastname, mpp_status, mpp_fleet, mpp_terminal, lgh_number, lgh_startdate, lgh_enddate, lgh_outstatus, lgh_driver1, lgh_class, lgh_class2 from cte 
  left join cte2 on mpp_id = lgh_driver1 where rn = '1' and mpp_id NOT IN ('UNKNOWN','TESDR','TESDR2') order by mpp_id

我想用这个存储过程做 3 件事:1) 创建一个表,2) 运行存储过程,3) 向表中插入数据。

【问题讨论】:

  • 您使用的是哪个 dbms? (上面的代码是特定于产品的。)

标签: sql-server tsql stored-procedures ddl create-table


【解决方案1】:

当你有一个正常的选择查询时:

SELECT *
FROM person
WHERE name = 'smith'

使用 INTO 制作表格:

SELECT *
INTO person_only_smith
FROM person
WHERE name = 'smith'

这只有在表不存在时才有效。如果表存在,请使用:

INSERT INTO person_only_smith
SELECT *
FROM person
WHERE name = 'smith'

-

在您的情况下,INTO 进入最终选择(不在 CTE 中)

Select 
mpp_id,
mpp_firstname,
mpp_lastname, 
... more columns ..
INTO your_table_name
FROM ...

现在,您说您希望此作业按计划运行,这有点暗示该表每次运行时都会有不同的名称。为简单起见,您可能希望先选择 #temp 表,然后使用动态 sql 将所有内容插入到实际的非临时表中。这意味着您可以拥有一个大而复杂的 SQL 块,但具有语法高亮以便于调试的好处,并且您的动态 sql 更小更简单:

WITH
...your ctes
)
SELECT
...
INTO #mytemptable
FROM ...

因为您的#mytemptable 是在执行动态sql 的命令之外创建的,所以动态可以访问它

DECLARE @sql VARCHAR(2000) = CONCAT('SELECT * INTO jobtable_', FORMAT(getutcdate(), 'yyyyMMddHHmm'), ' FROM #mytemptable');
EXEC (@sql)

请记住,如果您在动态 sql 中创建临时表,则它不适用于执行动态 sql 上下文之外的代码


最后说明;变化的表名通常很麻烦,正如这里所见,需要使用动态 sql 来使它们工作,甚至在前端应用程序中更动态地从它们中检索数据。考虑改为有一个固定的表名和一个指定作业日期的列。如果您首先将其选择到变量中,它将对每一行具有相同的值:

DECLARE @jobdate DATETIME = getutcdate();

INSERT INTO job_log (jobdate, list,of,other,columns)
SELECT @jobdate, *
FROM person
WHERE name = 'smith'

现在,这可以被索引以便快速检索,并且表名始终相同;全面减少编码和维护方面的麻烦

【讨论】:

  • 我在最后一个 Select 语句中添加了 INTO DriverSnapshot,存储过程成功运行,但是,我不知道它在哪里创建了放置所有数据的 DriverSnapshot。我如何找到它?谢谢。
  • SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE table_name = 'driversnapshot' 会给你什么回报?
  • 我实际上将表名更改为 Driver_Count 但存储过程仍然运行成功。当我执行查询以在 INFORMATION_SCHEMA.TABLES 中搜索 Driver_Count 时,它什么也不返回。
  • 我找到了这张桌子。这是发生了什么:当我运行存储过程时,即使它运行成功,它也不会创建表。如果我只是在 ALTER Procedure 行之后突出显示代码,它会创建表并填充数据。所以现在我需要弄清楚为什么它在运行存储过程时不起作用,但是如果我在存储过程中运行代码,那么表就可以工作。
  • 存储过程是否在禁止创建表的安全上下文中运行?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-23
  • 1970-01-01
相关资源
最近更新 更多