在过程中使用动态 sql 将数据插入模式表
Using dynamic sql in a procedure to insert data into schema tables
希望你们一切都好。
我一直在做一个项目,我需要存储有关我大学的数据,包括身份证号码、姓名、联系方式等。
我在创建能够将数据插入指定 schema.table_name 的存储过程时遇到了一些困难。该过程必须能够允许 EXEC 命令指定您希望将数据插入到哪个模式。 table_name 将对所有 14 个模式保持不变。以下代码示例是我想出的,但它似乎不起作用:
CREATE PROCEDURE AddStudent_proc(@campus varchar(50), @StudentID numeric(4,0), @Name varchar(50), @Surname varchar(50), @ID_numeric numeric(13,0), @Address varchar(100))
AS
BEGIN
DECLARE @dynamic varchar(MAX)
SET @dynamic = 'INSERT INTO ['+quotename(@campus)+'].Student_tbl(
StudentID,
Name,
Surname,
ID_numeric,
Address
)
VALUES('+quotename(@StudentID)+','+quotename(@Name)+','+quotename(@Surname)+','+quotename(@ID_numeric)+','+quotename(@Address)+');'
EXEC (@dynamic);
END
GO
我的整个结构都可以找到
对于此主题的任何帮助,我将不胜感激,因为我对 SQL 总体上还是一个新手。
提前致谢。
您不需要对数据使用 quotename
- 正如函数名称所暗示的那样,它应该与名称(A.K.A 标识符)一起使用。
此外,当您使用 quotename
时,它会在收到的值周围添加 [
和 ]
,因此无需再次添加它们(代码中的 ['+quotename(@campus)+']
)。
我建议对您现在的程序进行三项改进:
- 将
@campus
的数据类型更改为 sysname
- 这是 nvarchar(128) not null
的特殊数据类型同义词,被 SQL 服务器用于所有标识符。
- 将架构名称列入白名单。
这是防止 SQL 注入攻击的重要更改。
任何不能参数化的东西都需要列入白名单。
- 使用
sp_ExecuteSql
代替EXEC
这将产生更好的存储过程,因为它消除了 SQL Injection:
的威胁
CREATE PROCEDURE AddStudent_proc(
@campus sysname,
@StudentID numeric(4,0),
@Name varchar(50),
@Surname varchar(50),
@ID_numeric numeric(13,0),
@Address varchar(100)
)
AS
BEGIN
IF EXISTS(
SELECT 1
FROM Sys.Schemas
WHERE name = @campus
)
BEGIN
DECLARE @dynamic nvarchar(4000),
@paramDefinition nvarchar(4000)
SELECT @dynamic = N'INSERT INTO '+ quotename(@campus) + N'.Student_tbl (
StudentID,
Name,
Surname,
ID_numeric,
Address
)
VALUES(@StudentID, @Name, @Surname, @ID_numeric, @Address)',
@paramDefinition =
N'@StudentID numeric(4,0),
@Name varchar(50),
@Surname varchar(50),
@ID_numeric numeric(13,0),
@Address varchar(100)'
EXEC sp_executeSql @dynamic, @paramDefinition, @StudentID, @Name, @Surname, @ID_numeric, @Address;
END
END
GO
希望你们一切都好。
我一直在做一个项目,我需要存储有关我大学的数据,包括身份证号码、姓名、联系方式等。
我在创建能够将数据插入指定 schema.table_name 的存储过程时遇到了一些困难。该过程必须能够允许 EXEC 命令指定您希望将数据插入到哪个模式。 table_name 将对所有 14 个模式保持不变。以下代码示例是我想出的,但它似乎不起作用:
CREATE PROCEDURE AddStudent_proc(@campus varchar(50), @StudentID numeric(4,0), @Name varchar(50), @Surname varchar(50), @ID_numeric numeric(13,0), @Address varchar(100))
AS
BEGIN
DECLARE @dynamic varchar(MAX)
SET @dynamic = 'INSERT INTO ['+quotename(@campus)+'].Student_tbl(
StudentID,
Name,
Surname,
ID_numeric,
Address
)
VALUES('+quotename(@StudentID)+','+quotename(@Name)+','+quotename(@Surname)+','+quotename(@ID_numeric)+','+quotename(@Address)+');'
EXEC (@dynamic);
END
GO
我的整个结构都可以找到
对于此主题的任何帮助,我将不胜感激,因为我对 SQL 总体上还是一个新手。
提前致谢。
您不需要对数据使用 quotename
- 正如函数名称所暗示的那样,它应该与名称(A.K.A 标识符)一起使用。
此外,当您使用 quotename
时,它会在收到的值周围添加 [
和 ]
,因此无需再次添加它们(代码中的 ['+quotename(@campus)+']
)。
我建议对您现在的程序进行三项改进:
- 将
@campus
的数据类型更改为sysname
- 这是nvarchar(128) not null
的特殊数据类型同义词,被 SQL 服务器用于所有标识符。 - 将架构名称列入白名单。
这是防止 SQL 注入攻击的重要更改。
任何不能参数化的东西都需要列入白名单。 - 使用
sp_ExecuteSql
代替EXEC
这将产生更好的存储过程,因为它消除了 SQL Injection:
的威胁CREATE PROCEDURE AddStudent_proc(
@campus sysname,
@StudentID numeric(4,0),
@Name varchar(50),
@Surname varchar(50),
@ID_numeric numeric(13,0),
@Address varchar(100)
)
AS
BEGIN
IF EXISTS(
SELECT 1
FROM Sys.Schemas
WHERE name = @campus
)
BEGIN
DECLARE @dynamic nvarchar(4000),
@paramDefinition nvarchar(4000)
SELECT @dynamic = N'INSERT INTO '+ quotename(@campus) + N'.Student_tbl (
StudentID,
Name,
Surname,
ID_numeric,
Address
)
VALUES(@StudentID, @Name, @Surname, @ID_numeric, @Address)',
@paramDefinition =
N'@StudentID numeric(4,0),
@Name varchar(50),
@Surname varchar(50),
@ID_numeric numeric(13,0),
@Address varchar(100)'
EXEC sp_executeSql @dynamic, @paramDefinition, @StudentID, @Name, @Surname, @ID_numeric, @Address;
END
END
GO