我正在使用while循环动态创建表。将创建许多表。但是,运行代码时出现此错误。
“转换varchar值时转换失败”
不知道为什么,因为如果我用硬编码表名,它就可以了。
旧代码-
DECLARE @Count INT = (SELECT COUNT(*) FROM PayComponents) --This is how many
times im going to loop.
DECLARE @Pcomp INT = '1' --starting at 1
DECLARE @Table VARCHAR(10) = 'Pcomp' --Part of the table name
DECLARE @TableNo VARCHAR(10) --declaring for adding onto table name.
DECLARE @TableName VARCHAR(10) --declare to hold full table name
WHILE @Pcomp <= @Count --while 1 is less than or = to 61 loop
BEGIN
DECLARE @str VARCHAR(MAX)
SET @TableNo = CAST(@Pcomp AS VARCHAR(10))
SET @TableName = @Table + @TableNo --Full table name... Pcomp1, Pcomp2,
Pcomp3, Pcomp4 etc
SET @str = 'IF OBJECT_ID(''dbo.' + @TableName + ''', ''U'') IS NOT NULL //This is where i am getting the conversion error
Drop Table ' + @TableName + '
CREATE TABLE ' + @TableName + '
(
EeID INT,
EeRef VARCHAR(10),
Name VARCHAR(50),
PayCompID SMALLINT,
PayCompDesc VARCHAR(50),
RateLastMonth MONEY,
RateThisMonth MONEY
)
INSERT INTO ' + @TableName + ' (EeID, EeRef, Name, PayCompID,
PayCompDesc,
RateLastMonth)
SELECT
ed.EeID,
ed.EeRef,
CONCAT(Forename, '' '', Surname) AS ''Name'',
eec.PCompID,
eec.PCDescr,
eec.Rate
FROM EeDetails ed
INNER JOIN UnityEeComponents eec ON eec.EeRef = ed.EeRef
CROSS JOIN PayrollRuns pr
WHERE eec.PCompID = ' + @Pcomp + ' AND pr.RunID = (SELECT RunID FROM
PayrollRuns WHERE RunDate = ''2019-04-30'')
ORDER BY ed.EeID
UPDATE ' + @TableName + '
SET
' + @TableName + '.RateThisMonth = EeComponents.ECRate
FROM ' + @TableName + '
INNER JOIN
EeComponents
ON
' + @TableName +'.EeID = EeComponents.EeID
WHERE EeComponents.PCompID = ' + @Pcomp + ' AND EeComponents.RunID =
(SELECT RunID FROM PayrollRuns WHERE RunDate = ''2019-02-08'')
SET ' + @Pcomp + ' = ' + @Pcomp + ' + 1;'
END;
新代码-说明“逗号已成功完成”
虽然没有创建表。
DECLARE @Count INT = (SELECT COUNT(*) FROM PayComponents) --This is how many
times im going to loop
DECLARE @Pcomp INT = '1' --starting at 1
DECLARE @Table VARCHAR(10) = 'PComp' --Part of the table name
DECLARE @TableName VARCHAR(10) --declare to hold full table name
WHILE @Pcomp <= @Count --while 1 is less than or = to 61 loop
BEGIN
DECLARE @str VARCHAR(MAX)
SET @str = '
SET ' + @TableName + ' = CONCAT('+@Table+', '+CAST(@Pcomp AS VARCHAR(10))+')
IF OBJECT_ID(''dbo.' + QUOTENAME(@TableName) + ''', ''U'') IS NOT NULL
Drop Table ' + QUOTENAME(@TableName) + '
CREATE TABLE ' + QUOTENAME(@TableName) + '
(
EeID INT,
EeRef VARCHAR(10),
Name VARCHAR(50),
PayCompID SMALLINT,
PayCompDesc VARCHAR(50),
RateLastMonth MONEY,
RateThisMonth MONEY
)
INSERT INTO ' + QUOTENAME(@TableName) + ' (EeID, EeRef, Name, PayCompID,
PayCompDesc, RateLastMonth, RateThisMonth)
SELECT
ed.EeID,
ed.EeRef,
CONCAT(Forename, '' '', Surname),
eec.PCompID,
eec.PCDescr,
eec.Rate,
''0.00''
FROM EeDetails ed
INNER JOIN UnityEeComponents eec ON eec.EeRef = ed.EeRef
CROSS JOIN PayrollRuns pr
WHERE eec.PCompID = ' + QUOTENAME(@Pcomp) + ' AND pr.RunID = (SELECT RunID
FROM PayrollRuns WHERE RunDate = ''2019-04-30'')
ORDER BY ed.EeID
UPDATE ' + QUOTENAME(@TableName) + '
SET
' + QUOTENAME(@TableName) + '.RateThisMonth = EeComponents.ECRate
FROM ' + QUOTENAME(@TableName) + '
INNER JOIN
EeComponents
ON
' + QUOTENAME(@TableName) +'.EeID = EeComponents.EeID
WHERE EeComponents.PCompID = ' + CAST(@Pcomp AS VARCHAR(10)) + ' AND
EeComponents.RunID = (SELECT RunID FROM PayrollRuns WHERE RunDate = ''2019-
02-08'');'
EXEC (@str)
SET @Pcomp = CAST(@Pcomp AS VARCHAR(10)) + 1;
END;
任何帮助或建议将不胜感激。
答案 0 :(得分:0)
+运算符根据所应用的值的数据类型执行不同的操作。它执行数字运算(加法)或连接字符串。您有(摘要)
'....SET ' + @Pcomp + ' = ' + @Pcomp + ' + 1;'
@Pcomp是一个整数。另一个值是一个字符串。怎么了?要评估结果,必须将值转换为单个数据类型,以确定要执行的操作。那么选择哪种数据类型呢?当您的代码未明确指出要使用的代码时,会有rules-字符串的优先级最低。在这种情况下,引擎会尝试将您的字符串文字转换为整数-失败。
虽然可以解决您的迫在眉睫的问题,但您遇到的问题要大得多。您的循环是无限的,因为您不增加循环计数器。实际上,您不会执行所生成的动态查询。全部可修复-但更大的问题是为什么!
为什么需要在此处创建单独的表?您有一个标准化问题,应该重新考虑。
最后,您已经将非常特定的日期硬编码到查询逻辑中。尽管这可能暂时可行,但我看不到它将如何以通用的,持续的方式工作。