首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >SQL游标使用临时表中的表和字段名

SQL游标使用临时表中的表和字段名
EN

Stack Overflow用户
提问于 2016-06-16 15:28:25
回答 3查看 5.4K关注 0票数 6

首先,我要让大家知道,几年前我曾承诺过,在不需要游标的情况下,不要在SQL中使用游标。不幸的是,我认为我可能不得不在当前的情况下使用它,但它已经太久了,以至于我很难记住正确的语法。

基本上,我在查询中遇到了CONVERT_IMPLICIT问题,因为对于不同表中的相同字段,有不同的数据类型,所以我希望最终将它们转换为int。但要做到这一点,我需要检查是否可以将所有数据转换为int,以查看任务有多大。

下面的查询给出了数据库中包含列表中相关字段的所有表的列表;

代码语言:javascript
运行
复制
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'

给出这样的结果;

代码语言:javascript
运行
复制
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)。我有以下的计算,它的工作非常好;

代码语言:javascript
运行
复制
'SELECT  
CASE 
    WHEN COUNT(' + @FieldName + ') - SUM(ISNUMERIC(' + @FieldName + ')) > 0 
        THEN 1 
    ELSE 0 
END 
FROM ' + @TableName

并给出了我想要的结果。但是,我很难找到正确的语法来创建游标,游标将查看临时表中的每一行,并相应地运行此SQL。然后,它需要用查询(1或0)的结果更新temp表的最后一列。

这将需要在几百个数据库上运行,这就是为什么我需要这个列表是动态的,在某些数据库中很可能有自定义表(实际上,这很可能)。

如果有人能提供任何指导,我们将不胜感激。

谢谢

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-06-22 14:24:35

我对您的原始查询做了一些更改,但是这里有一些应该可以工作的地方。我过去曾做过类似的事情:

更改:

  • 将架构添加到源表??我的测试数据库在多个模式中具有匹配项。
  • 将数据类型更改为sysname、小get以匹配表定义或名称可能会被截断。 如果OBJECT_ID('tempdb..#BaseData')不是空删除表#BaseData;创建表#BaseData (Schema_Name sysname、Table_Name sysname、Field_Name sysname、Data_Type_Desc sysname、Data_Max_Length小型化、可转换位);声明@FieldName varchar(20);SET @FieldName = 'TestFieldName';插入#BaseData (Schema_Name、Table_Name、Field_Name、Data_Type_Desc、Data_Max_Length),选择s.name、o.name、c.name、t.namet.max_length FROM sys.columns c sys.types t ON c.user_type_id = t.user_type_id JOIN sys.objects o ON c.object_id = o.object_id sys.schemas s ON o.schema_id=s.schema_id,其中c.name像'%‘+ @FieldName + '%’和o.type_desc = 'USER_TABLE';-从#BaseData中选择*;声明@sName sysname、@tName sysname、@fName sysname、@sql VARCHAR(MAX);将c游标本地FAST_FORWARD声明为选择Schema_Name、Table_Name、Field_Name从#BaseData;打开c;从c中获取下一个为@sName、@tName、@fName;当@@FETCH_STATUS =0 BEGIN SET @sql = 'UPDATE #BaseData SET CASE =(选择CASE时,计数(‘+ @fName + ') - SUM(ISNUMERIC(’+ @fName + ')) >0时,则其他0结束可转换从#BaseData ( Schema_Name =‘+ @sName +’和Table_Name =‘+ @tName +’‘和Field_Name =’+ @fName +‘')中的+ @sName +。-选择@sql;EXEC(@sql);从c中获取NEXT到@sName,@tName,@fName;END CLOSE c;DEALLOCATE c;从#BaseData中选择*;
票数 3
EN

Stack Overflow用户

发布于 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)

代码语言:javascript
运行
复制
  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;
票数 2
EN

Stack Overflow用户

发布于 2016-06-17 05:54:27

我无法测试这个,但它应该能做你想要的。只需在创建临时表后将其插入:

代码语言:javascript
运行
复制
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;
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37863439

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档