2009-02-03 4 views
7

Sapete se c'è un modo rapido in SQL Server (tramite transact-sql) che potrei tagliare tutti i campi stringa del database.Taglia tutti i campi del database

+0

Intendevi aggiornare la lunghezza della colonna alla lunghezza massima trovata in un valore di quella colonna?Voglio dire come avere una colonna Nome nella tabella Persone dove Nome è VARCHAR (200) e in tutte le 10000 righe il Nome più lungo è 23 per modificare la colonna in VARCHAR (23)? –

risposta

19

Nessun cursori. Copia e incolla l'output. Funziona anche per SQL 2000, che non ha varchar (max). Questo può essere facilmente esteso per aggiungere una linea GO alla fine di ogni UPDATE, se lo si desidera.

SELECT SQL 
FROM (  SELECT t.TABLE_CATALOG 
       ,  t.TABLE_SCHEMA 
       ,  t.TABLE_NAME 
       ,  0    SORT 
       ,  'UPDATE ' + QUOTENAME(t.TABLE_CATALOG) + '.' + QUOTENAME(t.TABLE_SCHEMA) + '.' + QUOTENAME(t.TABLE_NAME)  SQL 
       FROM INFORMATION_SCHEMA.TABLES  t 
       JOIN INFORMATION_SCHEMA.COLUMNS  c 
        ON t.TABLE_CATALOG = c.TABLE_CATALOG 
        AND t.TABLE_SCHEMA = c.TABLE_SCHEMA 
        AND t.TABLE_NAME = c.TABLE_NAME 
       WHERE t.TABLE_TYPE = 'BASE TABLE' 
       AND c.DATA_TYPE  IN ('char','nchar','varchar','nvarchar') 
       GROUP BY  t.TABLE_CATALOG 
       ,    t.TABLE_SCHEMA 
       ,    t.TABLE_NAME 
       UNION ALL 
       SELECT x.TABLE_CATALOG 
       ,  x.TABLE_SCHEMA 
       ,  x.TABLE_NAME 
       ,  CASE WHEN x.COLUMN_NAME_MIN  = y.COLUMN_NAME 
           THEN 1 
           ELSE 2 
         END              SORT 
       ,  CASE WHEN x.COLUMN_NAME_MIN  = y.COLUMN_NAME 
           THEN 'SET  ' 
           ELSE ' ,  ' 
         END + y.SQL            SQL 
       FROM (  SELECT t.TABLE_CATALOG 
           ,  t.TABLE_SCHEMA 
           ,  t.TABLE_NAME 
           ,  MIN(c.COLUMN_NAME)  COLUMN_NAME_MIN 
           FROM INFORMATION_SCHEMA.TABLES  t 
           JOIN INFORMATION_SCHEMA.COLUMNS  c 
            ON t.TABLE_CATALOG = c.TABLE_CATALOG 
            AND t.TABLE_SCHEMA = c.TABLE_SCHEMA 
            AND t.TABLE_NAME = c.TABLE_NAME 
           WHERE t.TABLE_TYPE = 'BASE TABLE' 
           AND c.DATA_TYPE  IN ('char','nchar','varchar','nvarchar') 
           GROUP BY  t.TABLE_CATALOG 
           ,    t.TABLE_SCHEMA 
           ,    t.TABLE_NAME 
         )  x 
       JOIN (  SELECT t.TABLE_CATALOG 
           ,  t.TABLE_SCHEMA 
           ,  t.TABLE_NAME 
           ,  c.COLUMN_NAME 
           ,  QUOTENAME(c.COLUMN_NAME) + ' = LTRIM(RTRIM(' + QUOTENAME(c.COLUMN_NAME) + '))' SQL 
           FROM INFORMATION_SCHEMA.TABLES  t 
           JOIN INFORMATION_SCHEMA.COLUMNS  c 
            ON t.TABLE_CATALOG = c.TABLE_CATALOG 
            AND t.TABLE_SCHEMA = c.TABLE_SCHEMA 
            AND t.TABLE_NAME = c.TABLE_NAME 
           WHERE t.TABLE_TYPE = 'BASE TABLE' 
           AND c.DATA_TYPE  IN ('char','nchar','varchar','nvarchar') 
         )  y 
        ON x.TABLE_CATALOG = y.TABLE_CATALOG 
        AND x.TABLE_SCHEMA = y.TABLE_SCHEMA 
        AND x.TABLE_NAME = y.TABLE_NAME 
     )  x 
ORDER BY  x.TABLE_CATALOG 
,    x.TABLE_SCHEMA 
,    x.TABLE_NAME 
,    x.SORT 
,    x.SQL 
+0

+1. Ho salvato la giornata come qualsiasi cosa –

13

La tua domanda è un po 'vaga ma è questo quello che cerchi?

UPDATE mytable SET mycolumn= LTRIM(RTRIM(mycolumn)) 

che rimuove gli spazi iniziali e finali da tutti i valori nella colonna 'MyColumn' nella tabella 'miatabella'.

3

ciclo su INFORMATION_SCHEMA.COLUMNS e RTRIM le colonne varchar/nvarchar creando l'istruzione di aggiornamento dinamico

2

Basta fare in modo che si sta facendo un assetto sui campi di stringhe VARCHAR, non campi CHAR :)

che wouldn fare molto bene

+0

Che dire degli spazi guida? – alyssackwan

+0

Ok, LTRIM ha qualche merito su una colonna CHAR. Solo non RTRIM. – BradC

3

Se qualcuno sa come fare questo senza un cursore, si prega di postare:

DECLARE @CRLF AS varchar(2) 
SET @CRLF = CHAR(13) + CHAR(10) 
DECLARE @TAB AS varchar(1) 
SET @TAB = CHAR(9) 

DECLARE @template AS varchar(max) 
SET @template = 'UPDATE {@OBJECT_NAME}' + @CRLF + 'SET {@column_list}' 

DECLARE c CURSOR FAST_FORWARD 
    FOR SELECT DISTINCT 
       QUOTENAME(T.TABLE_CATALOG) + '.' + QUOTENAME(T.TABLE_SCHEMA) 
       + '.' + QUOTENAME(T.TABLE_NAME) AS [OBJECT_NAME] 
     FROM INFORMATION_SCHEMA.TABLES AS T 
     INNER JOIN INFORMATION_SCHEMA.COLUMNS AS C 
       ON T.TABLE_CATALOG = C.TABLE_CATALOG 
        AND T.TABLE_SCHEMA = C.TABLE_SCHEMA 
        AND T.TABLE_NAME = C.TABLE_NAME 
        AND T.TABLE_TYPE = 'BASE TABLE' 
        AND C.DATA_TYPE IN ('varchar', 'nvarchar') 
     ORDER BY 1 

DECLARE @OBJECT_NAME AS sysname 

OPEN c 

FETCH NEXT FROM c INTO @OBJECT_NAME 
WHILE @@FETCH_STATUS = 0 
    BEGIN 
     DECLARE @column_list AS varchar(max) 
     SELECT @column_list = COALESCE(@column_list + @CRLF + @TAB + ',', '') 
       + QUOTENAME(C.COLUMN_NAME) + ' = LTRIM(RTRIM(' 
       + QUOTENAME(C.COLUMN_NAME) + '))' 
     FROM INFORMATION_SCHEMA.COLUMNS AS C 
     WHERE C.DATA_TYPE IN ('varchar', 'nvarchar') 
       AND QUOTENAME(C.TABLE_CATALOG) + '.' 
       + QUOTENAME(C.TABLE_SCHEMA) + '.' + QUOTENAME(C.TABLE_NAME) = @OBJECT_NAME 
     ORDER BY C.ORDINAL_POSITION 

     PRINT REPLACE(REPLACE(@template, '{@column_list}', @column_list), 
         '{@OBJECT_NAME}', @OBJECT_NAME) 

     FETCH NEXT FROM c INTO @OBJECT_NAME 
    END 

CLOSE c 

DEALLOCATE c 
+0

Fa un conteggio del ciclo while;) – AlexCuse

0

Grazie ragazzi,

codice Entaroadun funzionato abbastanza bene per me, ho dovuto fare alcune piccole modifiche ai miei requierements, ed inoltre ho dovuto resettare @colum_list ad ogni iterazione.

... 
    PRINT REPLACE(REPLACE(@template, '{@column_list}', @column_list), 
          '{@OBJECT_NAME}', @OBJECT_NAME) 
    PRINT 'GO' 
    SELECT @column_list = null 
      FETCH NEXT FROM c INTO @OBJECT_NAME 
... 
0

- V Veloce e sporco!

- Se questo è per generare codice da eseguire su una singola tabella, eseguire questo codice con l'output di testo;

SET NOCOUNT su

dichiarano nvarchar @Table (100) selezionare + @Table + 'SET' SELEZIONA = @Table 'YourTableHere'

SELEZIONA 'UPDATE' '[' + column_name + ' ] = '+ 'LTRIM (RTRIM ([' + column_name + '])),' FROM INFORMATION_SCHEMA.COLUMNS DOVE table_name = @Table E DATA_TYPE LIKE '% CHAR%'

- Esegui come output di testo (Interrogazione/Risultati in ... Risultati in testo - Copia e incolla l'output di testo (esclusa l'ultima virgola) in una nuova finestra di query ed eseguilo.

0

OK, era veloce e sporco ma sono stato sufficientemente motivato da un progetto in corso per farlo 'correttamente' - e anche senza cursori, ma un piccolo trucco di concatenazione sql. fa uso di SQL dinamico però:

--exec spGenerateTrimStatements 'StaticImportMaturities' 
ALTER PROCEDURE  spGenerateTrimStatements 
    (
      @TableName NVARCHAR(100) 
    ) 
AS 
    DECLARE @Cr char(2),  
        @OutputString nvarchar(max) 

    SELECT @Cr = CHAR(13) + CHAR(10) 
    SET  NOCOUNT ON 

    -- Create table to store commands 
    CREATE TABLE #tOutput(OutputText nvarchar(500), RowID int identity(1,1)) 

    -- Build up commands 
    INSERT #tOutput(OutputText) 
    SELECT 'UPDATE ' + @TableName + ' SET ' 

    INSERT #tOutput(OutputText) 
    SELECT '[' + Column_Name + '] = ' + 'LTRIM(RTRIM([' + Column_Name + '])), ' 
    FROM INFORMATION_SCHEMA.Columns 
    WHERE Table_Name = @TableName 
     AND Data_Type LIKE '%CHAR%' 

    --  Trim last comma 
    UPDATE #tOutput 
    SET    OutputText = LEFT(OutputText, LEN(OutputText)-1) 
    WHERE RowID = (SELECT Max(RowID) FROM #tOutput) 

    -- use subselect to concatenate the command string 
    SELECT @OutputString = ISNULL(@OutputString, '') + ISNULL(OutputText, '') 
    FROM (SELECT OutputText 
      FROM #tOutput) TextOutput 

    -- run the command 
    EXEC sp_ExecuteSQL @OutputString 
1

Aggiornato la risposta di Dan di utilizzare tutte le tabelle nel database. Basta eseguire lo snippet e copiare il risultato da eseguire.

SELECT 'UPDATE [' + TABLE_SCHEMA + '].[' + TABLE_NAME + '] SET [' + Column_Name + '] = ' + 'LTRIM(RTRIM([' + Column_Name + ']))' 
FROM INFORMATION_SCHEMA.Columns c 
WHERE Data_Type LIKE '%CHAR%'