SQL Server 2019 replace function throws error that data type text is invalid for argument 1 of replace function

tv6aics1  于 2023-10-15  发布在  SQL Server
关注(0)|答案(1)|浏览(153)

I have written a query to find all tables from information schema and replace http by https from columns.But for text type column my query is not working.Below is the script written for it.

It is not working even it is converted to varchar

DECLARE @DatabaseName NVARCHAR(255) = 'LOTSONLINE';
DECLARE @TableName NVARCHAR(255);
DECLARE @ColumnName NVARCHAR(255);
DECLARE @Sql NVARCHAR(MAX);
-- Create a cursor to loop through tables and columns
DECLARE tableCursor CURSOR FOR
SELECT 
    t.TABLE_NAME AS TableName,
    c.COLUMN_NAME AS ColumnName
FROM INFORMATION_SCHEMA.TABLES t
JOIN INFORMATION_SCHEMA.COLUMNS c ON t.TABLE_NAME = c.TABLE_NAME
WHERE EXISTS (
    SELECT 1
    FROM INFORMATION_SCHEMA.COLUMNS AS c2
    WHERE c2.TABLE_NAME = t.TABLE_NAME
      --AND c2.DATA_TYPE IN ('varchar', 'nvarchar')
)
AND t.TABLE_TYPE = 'BASE TABLE' AND COLUMNPROPERTY(object_id(t.TABLE_SCHEMA+'.'+t.TABLE_NAME), c.COLUMN_NAME, 'IsIdentity')=0
AND c.DATA_TYPE IN('varchar', 'nvarchar','text','ntext');

-- Open the cursor
OPEN tableCursor;
-- Loop through tables and columns
FETCH NEXT FROM tableCursor INTO @TableName, @ColumnName;
WHILE @@FETCH_STATUS = 0
BEGIN
    SET @Sql = '
        DECLARE @StartTime DATETIME = GETDATE();
        DECLARE @ErrorMessage NVARCHAR(MAX);
        DECLARE @FailedRowNumber INT;

        BEGIN TRY
            UPDATE ' + QUOTENAME(@TableName) + '
            SET ' + QUOTENAME(@ColumnName) + ' = REPLACE('+CONVERT(NVARCHAR(MAX), QUOTENAME(@ColumnName) )+ ', ''http://'', ''https://'');
            SET @FailedRowNumber = 0;           
        END TRY
        BEGIN CATCH
            SET @ErrorMessage = ERROR_MESSAGE();
            SET @FailedRowNumber = ERROR_LINE(); 
        END CATCH;

        DECLARE @EndTime DATETIME = GETDATE();
                ';
    --select @Sql
    --return
    -- Execute dynamic SQL
    --EXEC sp_executesql @Sql;

    FETCH NEXT FROM tableCursor INTO @TableName, @ColumnName;
END;

-- Close and deallocate the cursor
CLOSE tableCursor;
DEALLOCATE tableCursor;
fdx2calv

fdx2calv1#

You seem to have a typo:

+ ' = REPLACE('+CONVERT(NVARCHAR(MAX), QUOTENAME(@ColumnName) )+ ', ''http://'', ''https://'');

Should be:

+ ' = REPLACE(CONVERT(NVARCHAR(MAX), ' + QUOTENAME(@ColumnName) + ' ) ''http://'', ''https://'');

In other words: you need to put that CONVERT inside the dynamic SQL.

  • Use sys rather than INFORMATION_SCHEMA which is for compatibility only and can be unreliable.
  • The EXISTS doesm't make any sense, so I've removed it. Likewise, a text column can't be an identity so you don't need to check for it.
  • You can update all columns in one UPDATE statement.
  • You don't need a cursor, you can build one big dynamic SQL batch using STRING_AGG .
  • Might be best to add some kind of WHERE so you are not updating all rows.
DECLARE @Sql NVARCHAR(MAX);

SELECT
  @sql = STRING_AGG('
UPDATE t 
SET ' + c.updateColumns + '
FROM ' + QUOTENAME(s.name) + '.' + QUOTENAME(t.name) + ' t;', '

')
FROM sys.tables t
JOIN sys.schemas s ON s.schema_id = t.schema_id
CROSS APPLY (
    SELECT
      updateColumns = STRING_AGG(CONVERT(nvarchar(max), '
' + QUOTENAME(c.name) + ' = REPLACE(CONVERT(nvarchar(max), t.' + QUOTENAME(c.name) + '), ''http://'', ''https://'')'
      ), ',')
    FROM sys.columns c
    JOIN sys.types typ ON typ.user_type_id = c.user_type_id
    WHERE typ.name IN ('varchar', 'nvarchar', 'text', 'ntext')
      AND c.object_id = t.object_id
) c;

PRINT @sql; -- your friend

EXEC sp_executesql @sql;

相关问题