SQL Server:选择表的列,然后选择前1个值

时间:2017-08-30 04:06:05

标签: sql-server dynamic-sql

有没有办法选择表的列,然后分配该列的前1个值。

例如

TABLENAME | COLUMNNAME | VALUE
----------+------------+---------------
TABLE 1   | COLUMN 1   | COLUMN 1 VALUE
TABLE 1   | COLUMN 2   | COLUMN 2 VALUE

更新

DECLARE @tableCOLS TABLE (tablename varchar(255) , colname varchar(255));   

        BEGIN
            SET @MyCursor = CURSOR FOR
            SELECT DISTINCT tablename FROM @tableid
            OPEN @MyCursor 
            FETCH NEXT FROM @MyCursor 
            INTO @MyField2
            WHILE @@FETCH_STATUS = 0 
                BEGIN

                    INSERT INTO @tableCOLS
                    SELECT @MyField2 , COLUMN_NAME
                    FROM INFORMATION_SCHEMA.COLUMNS
                    WHERE TABLE_NAME = @MyField2



                FETCH NEXT FROM @MyCursor 
                INTO @MyField2 
                END; 
            CLOSE @MyCursor ;
            DEALLOCATE @MyCursor;
        END;    
        SELECT * from @tableCOLS
    END;

我将表格列提取到动态表格,然后我想在我在表格中提取的列中插入某个数据的值

3 个答案:

答案 0 :(得分:1)

我刚试过这个并且它可以用来治疗

DECLARE @Result TABLE (TableName VARCHAR(50), Col VARCHAR(50), MaxValue VARCHAR(50), MaxSQL NVARCHAR(4000));
DECLARE @TableName VARCHAR(50), @Col VARCHAR(50), @MaxSQL NVARCHAR(4000), @MaxValue VARCHAR(50)

-- Load all tables and columns of interest
INSERT INTO @Result
(TableName, Col, MaxSQL)
select 
object_name(object_id),
name,
'SELECT @C = MAX(' + name + ') FROM ' + object_name(object_id)
from sys.columns where object_name(object_id) = 'Table1'

-- For each row, run the dynamic SQL and update back into table
DECLARE c CURSOR FOR 
SELECT TableName, Col, MaxSQL FROM @Result

OPEN c

FETCH NEXT FROM C INTO @TableName, @Col, @MaxSQL

WHILE @@FETCH_STATUS = 0
BEGIN
    EXEC sp_ExecuteSQL @MaxSQL, N'@C VARCHAR(50) OUTPUT', @C = @MaxValue OUTPUT

    UPDATE @Result SET MaxValue = @MaxValue WHERE TableName = @TableName AND Col = @Col;

    FETCH NEXT FROM C INTO @TableName, @Col, @MaxSQL
END


CLOSE c;
DEALLOCATE c;

-- Show the results
SELECT * FROM @Result;

答案 1 :(得分:0)

不需要使用循环或游标来执行此操作。看看以下......

SET NOCOUNT ON;

DECLARE @Object_id INT = OBJECT_ID('DataBaseName.Schema.TableName');

IF OBJECT_ID('tempdb..#TableCols', 'U') IS NOT NULL 
DROP TABLE #TableCols;

CREATE TABLE #TableCols (
    SchemaName sysname,
    TableName sysname,
    ColumnName sysname,
    ColumnID INT NOT NULL,
    Value NVARCHAR(MAX) NULL 
    );
INSERT #TableCols (SchemaName, TableName, ColumnName, ColumnID)
SELECT 
    s.name,
    o.name,
    c.name,
    c.column_id
FROM
    sys.objects o
    JOIN sys.schemas s
        ON o.schema_id = s.schema_id
    JOIN sys.columns c
        ON o.object_id = c.object_id
WHERE
    o.type = 'U'
    AND o.object_id = @Object_id
ORDER BY 
    c.column_id;

DECLARE 
    @CrossCols VARCHAR(MAX) = N'',
    @TopVal NVARCHAR(10) = N'',
    @Table sysname = N'', 
    @sql NVARCHAR(MAX) = N'',
    @DeBug BIT = 0;     -- 1 = PRINT ; 0 = EXECUTE

SELECT 
    @CrossCols = CONCAT(@CrossCols, N',
                                (', tc.ColumnID, N', CAST(t.[', tc.ColumnName, N'] AS NVARCHAR(MAX)))'),
    @TopVal = tc.ColumnID,
    @Table = CONCAT(tc.SchemaName, '.', tc.TableName)
FROM 
    #TableCols tc
ORDER BY 
    tc.ColumnID;

SET @sql = CONCAT(N'    
UPDATE tc SET 
    tc.Value = t.ColumnValue
FROM
    #TableCols tc
    JOIN (
        SELECT TOP (', @TopVal, N')
            x.*
        FROM
            ', @Table, N' t
            CROSS APPLY ( VALUES', STUFF(@CrossCols, 1, 1, ''), N'
                            ) x (ColumnID, ColumnValue)
        ) t
        ON tc.ColumnID = t.ColumnID;')

IF @DeBug = 1
BEGIN 
    EXEC dbo.LongPrint @sql;
END;
ELSE
BEGIN
    EXEC(@sql);
    SELECT * FROM #TableCols tc;
END;

答案 2 :(得分:0)

试一试......

DECLARE @Table VARCHAR(MAX) = 'Customer'

SELECT t.name                                                                                                         AS [Table]
,      c.name                                                                                                         AS [Column]
,      cmd.mycmd                                                                                                     
,      TYPE_NAME(c.user_type_id)                                                                                      AS [Type]
,      c.max_length                                                                                                   AS [Size]
,      CASE WHEN c.is_nullable = 1 THEN ''
                                   ELSE 'No Nulls' END                                                                AS Nullable
,      ROW_NUMBER() OVER ( PARTITION BY t.name ORDER BY c.name ASC )                                                  AS rnk
,      CASE WHEN EXISTS ( SELECT 1
    FROM sys.columns c2
    WHERE c2.object_id = t.object_id
        AND c2.name IN ( SELECT *
        FROM dbo.fnSplit('Fieldnames,ToSkip', ',') ) ) THEN 'Y'
                                                                                                         ELSE 'N' END AS [CreModDeLs]
    into #MyTempTable
FROM        sys.columns                                                                                                   AS c  
JOIN        sys.tables                                                                                                    AS t   ON c.object_id = t.object_id
cross apply (Select 'Select top 1 @Val = cast(' + c.name + ' as varchar(max)) from  ' + t.name + ' Order by 1 desc' as mycmd)    cmd
WHERE t.name LIKE @Table
ORDER BY t.name
,        c.name

alter table #MyTempTable add [Id] integer identity(1,1)
alter table #MyTempTable add [Top1Val] Varchar(max)

Declare @DynamicSQL as nvarchar(1000);
Declare @dynamicparamdec nvarchar(1000) = '@val Varchar(max) Output'

Declare @valueofid as int
Declare @returnval as varchar(max)

Declare @Id integer

DECLARE #MyCursor CURSOR FAST_FORWARD
FOR
SELECT id
,      mycmd
FROM #MyTempTable
where type <> 'image'

OPEN #MyCursor

FETCH #MyCursor INTO @id, @DynamicSQL

WHILE @@fetch_status = 0
BEGIN
    print @dynamicsql
    execute sp_executesql @DynamicSQL
    ,                     @dynamicparamdec
    ,                     @returnval output

    update #MyTempTable
    set Top1Val = @returnval
    where id = @id
    FETCH #MyCursor INTO @id, @DynamicSQL
END
--Close the cursor, if it is empty then deallocate it:
IF ( SELECT CURSOR_STATUS('global', '#MyCursor') ) >= -1
BEGIN
    IF ( SELECT CURSOR_STATUS('global', '#MyCursor') ) > -1
    BEGIN
        CLOSE #MyCursor
    END
    DEALLOCATE #MyCursor
END


select * from #MyTempTable