首先,我要让大家知道,几年前我曾承诺过,在不需要游标的情况下,不要在SQL中使用游标。不幸的是,我认为我可能不得不在当前的情况下使用它,但它已经太久了,以至于我很难记住正确的语法。
基本上,我在查询中遇到了CONVERT_IMPLICIT
问题,因为对于不同表中的相同字段,有不同的数据类型,所以我希望最终将它们转换为int
。但要做到这一点,我需要检查是否可以将所有数据转换为int,以查看任务有多大。
下面的查询给出了数据库中包含列表中相关字段的所有表的列表;
IF OBJECT_ID('tempdb..#BaseData') IS NOT NULL DROP TABLE #BaseData
GO
CREATE TABLE #BaseData (Table_Name varchar(100), Field_Name varchar(100), Data_Type_Desc varchar(20), Data_Max_Length int, Convertible bit)
DECLARE @FieldName varchar(20); SET @FieldName = 'TestFieldName'
INSERT INTO #BaseData (Table_Name, Field_Name, Data_Type_Desc, Data_Max_Length)
SELECT
o.name ,c.name ,t.name ,t.max_length
FROM sys.columns c
JOIN sys.types t
ON c.user_type_id = t.user_type_id
JOIN sys.objects o
ON c.object_id = o.object_id
WHERE c.name LIKE '%' + @FieldName + '%'
AND o.type_desc = 'USER_TABLE'
给出这样的结果;
Table_Name Field_Name Data_Type_Desc Data_Max_Length Convertible
Table1 TestFieldName varchar 8000 NULL
Table2 TestFieldName nvarchar 8000 NULL
Table3 TestFieldName int 4 NULL
Table4 TestFieldName varchar 8000 NULL
Table5 TestFieldName varchar 8000 NULL
我想做的是检查相关表和字段中的所有数据是否可以转换为int,并更新“可转换”字段(如果存在无法转换的数据,则为0)。我有以下的计算,它的工作非常好;
'SELECT
CASE
WHEN COUNT(' + @FieldName + ') - SUM(ISNUMERIC(' + @FieldName + ')) > 0
THEN 1
ELSE 0
END
FROM ' + @TableName
并给出了我想要的结果。但是,我很难找到正确的语法来创建游标,游标将查看临时表中的每一行,并相应地运行此SQL。然后,它需要用查询(1或0)的结果更新temp表的最后一列。
这将需要在几百个数据库上运行,这就是为什么我需要这个列表是动态的,在某些数据库中很可能有自定义表(实际上,这很可能)。
如果有人能提供任何指导,我们将不胜感激。
谢谢
发布于 2016-06-22 14:24:35
我对您的原始查询做了一些更改,但是这里有一些应该可以工作的地方。我过去曾做过类似的事情:
更改:
发布于 2016-06-16 15:42:17
如果我理解你的问题,我会做这样的事情来识别那些不作为int的记录。
您没有说明所使用的Server的哪个版本;TRY_CAST和TRY_CONVERT是2012年或更高版本。
声明@test为表(字段);
插入@test (字段)值( N'1‘),(N’);
从@test中选择字段,其中TRY_CAST(字段为INT)为空;
-这是游标的基本sql语法(https://msdn.microsoft.com/en-us/library/ms180169.aspx)
DECLARE @parameter [sysname];
BEGIN
DECLARE [field_cursor] CURSOR
FOR
SELECT [value]
FROM [<schema>].[<table>];
OPEN [field_cursor];
FETCH NEXT FROM [field_cursor] INTO @parameter;
WHILE @@FETCH_STATUS = 0
BEGIN
-- do something really interesting here
FETCH NEXT FROM [field_cursor] INTO @parameter;
END;
CLOSE [field_cursor];
DEALLOCATE [field_cursor];
END;
发布于 2016-06-17 05:54:27
我无法测试这个,但它应该能做你想要的。只需在创建临时表后将其插入:
DECLARE @tName VARCHAR(20),
@fName VARCHAR(20),
@dType VARCHAR(20),
@dLength INT,
@sql VARCHAR(MAX);
DECLARE c CURSOR LOCAL FAST_FORWARD FOR
SELECT Table_Name,
Field_Name,
Data_Type_Desc,
Data_Max_Length
FROM #BaseData;
OPEN c;
FETCH NEXT FROM c INTO @tName, @fName, @dType, @dLength;
WHILE @@FETCH_STATUS = 0
BEGIN
IF((COUNT(@FieldName) - SUM(ISNUMERIC(@FieldName))) > 0)
BEGIN
SET @sql = 'UPDATE ' + @tName + ' SET Convertible = 1 WHERE Table_Name = ''' + @tName + '''';
END
ELSE
BEGIN
SET @sql = 'UPDATE ' + @tName + ' SET Convertible = 0 WHERE Table_Name = ''' + @tName + '''';
END
EXEC(@sql);
FETCH NEXT FROM c INTO @TableName, @FieldName, @DataType, @DataLength;
END
CLOSE c;
DEALLOCATE c;
https://stackoverflow.com/questions/37863439
复制相似问题