我已经创建了一个存储过程来练习使用游标,我遇到了特殊字符的问题,例如,如果last_name包含单引号,我就遇到了一个错误,我需要以某种方式对其进行转义,我该怎么做呢?我不知道这些字段中包含哪些特殊字符,我试过使用QUOTENAME(d.last_name),但它不起作用
CREATE OR alter PROCEDURE list_employees
AS
BEGIN
DECLARE cursore CURSOR FAST_FORWARD FOR SELECT TOP(20) d.id, d.first_name, d.last_name, cd.contact
FROM employees d
JOIN contacts cd ON cd.fk_employee= d.id
ORDER BY d.id;
DECLARE @id_employee VARCHAR(36);
DECLARE @first_name VARCHAR(50);
DECLARE @last_name VARCHAR(50);
DECLARE @contact VARCHAR(255);
DECLARE @insert_statement varchar(1000);
IF OBJECT_ID('dbo.list_employees', 'U') IS NOT NULL
BEGIN
DROP TABLE dbo.list_employees;
END
OPEN cursore;
FETCH NEXT FROM cursore INTO @id_employee , @first_name , @cognome, @contatto ;
if(@@FETCH_STATUS = 0)
BEGIN
CREATE TABLE dbo.list_employees(id_employee VARCHAR(36), first_name VARCHAR(50), last_name VARCHAR(50), contact VARCHAR(255))
END
WHILE @@FETCH_STATUS = 0
BEGIN
SET @insert_statement = 'INSERT INTO list_employees SELECT '''+@id_employee +''', '''+@first_name +''', '''+@last_name +''','''+ @contact +''''
exec(@insert_statement )
FETCH NEXT FROM cursore INTO @id_employee , @first_name , @last_name , @contact ;
END
CLOSE cursore;
DEALLOCATE cursore;
END;
2条答案
按热度按时间ujv3wf0j1#
由于您的代码删除了一个现有的表,然后重新创建它,我怀疑这个过程是一个奇怪的方式来获得“当前前20名”。而不是使用光标和各种麻烦,这将大大简化为使用视图。没有必要不断删除一个表,然后重新填充它。
您的视图可能如下所示。
jw5wzhpr2#
首先,让我们掩盖一下为什么你所拥有的东西不起作用;这是因为你注入了应该是参数的值。2具体来说,这两行是原因:
事实上,这里有两个坏习惯:
1.注入未经整理的值(一个巨大的安全漏洞)
1.使用
EXEC(@SQL)
语法,而不是sys.sp_executesql
,这意味着您 * 不能 * 参数化您的语句。如果您将语句参数化,那么您遇到的问题就会消失:
当然,这就提出了一个问题:为什么要使用动态SQL,这个语句没有什么动态的。这并不是说表在执行之前可能不存在,就像表不存在时引擎可以延迟验证一样,而你在同一个作用域中对表进行
CREATE
。也许表的定义正在改变?我 * 希望 * 不会。但是,正如前面提到的,这里并不真正需要
CURSOR
。虽然您声明您正在练习它们,但 * 很少 * 需要它们,并且将这样的东西更改为使用RBARCURSOR
会对性能造成很大影响。您实际上应该使用基于集合的INSERT
:或者,更好的方法是使用
VIEW
,就像Sean在他们的answer中演示的那样。