0

这里可以回答大约 10 个不同的子问题,但主要问题在标题中。TLDR 版本:我有一个如下例所示的表格,我想替换整个表格中的所有双引号。有没有一种简单的方法可以做到这一点?

我使用光标的解决方案似乎相当简单。我知道 SQL Server 社区中有一些 CURSOR 仇恨(运行时不好?)。CURSOR 在什么时候(num 行和/或 num 列)会发臭?

创建可重现的示例表

    DROP TABLE IF EXISTS #example;
    CREATE TABLE #example (
       NumCol  INT
      ,CharCol  NVARCHAR(20)
      ,DateCol  NVARCHAR(100)
      );
      
    INSERT INTO #example VALUES
    (1, '"commas, terrible"',  '"2021-01-01 20:15:57,2021:04-08 19:40:50"'),
    (2, '"loadsrc,.txt"', '2020-01-01 00:00:05'),
    (3, '".txt,from.csv"','1/8/2021 10:14')

现在,我确定的解决方案是:

  1. 为每一列手动更新UPDATE X SET CharCol = REPLACE(CharCol, '"','')。在超过 2 列 IMO 上做这件事非常烦人。
  2. 使用 CURSOR 进行更新(类似于 SQL Server 上令人讨厌的复杂外观解决方案 - SQL 替换整个数据库中所有表中的所有列

使用 CURSOR 替换字符

这与所有与光标相关的脚本有点复杂,但在其他方面似乎效果很好。

-- declare variable to store colnames, cursor to filter through list, string for dynamic sql code
DECLARE  @colname   VARCHAR(10)
        ,@sql       VARCHAR(MAX)
        ,@namecursor CURSOR;

-- run cursor and set colnames and update table
SET @namecursor = CURSOR FOR SELECT ColName FROM #colnames
OPEN @namecursor;  
FETCH NEXT FROM @namecursor INTO @colname;  

WHILE (@@FETCH_STATUS <> -1)  -- alt: WHILE @@FETCH_STATUS = 0
    BEGIN;  
        SET @sql = 'UPDATE #example SET '+@colname+' = REPLACE('+@colname+', ''"'','''')'
        EXEC(@sql); -- parentheses VERY important: EXEC(sql-as-string) NOT EXEC storedprocedure
        FETCH NEXT FROM @namecursor INTO @colname;  
    END;  
 
    CLOSE @namecursor;  
    DEALLOCATE @namecursor;  
    GO  

-- see results
SELECT * FROM #example

子问题:虽然我在其他地方的数据库中看到过它,但对于这个特定的示例,我在 Excel 中打开一个 .csv 文件并将其导出为制表符分隔。有没有办法在没有双引号的情况下更改要导出的设置?如果我没记错BULK INSERT的话,没有办法处理这个问题,也没有办法处理导入带有额外逗号的 csv 文件。

是的,我会假装我很好,日期列中有一个日期时间列表(需要 varchar 数据类型)。

4

2 回答 2

0

您可以尝试这种方法,速度不快,但易于输入(或生成)。

SELECT NumCol = y.value('(NumCol/text())[1]','int')
      ,CharCol = y.value('(CharCol/text())[1]','nvarchar(100)')
      ,DateCol = y.value('(DateCol/text())[1]','nvarchar(100)')
FROM #example e
CROSS APPLY(SELECT e.* FOR XML PATH('')) A(x)
CROSS APPLY(SELECT CAST(REPLACE(A.x,'"','') AS XML)) B(y);

简而言之:

  • 第一个APPLY将所有列转换为无XML。
  • 不使用,TYPEthis 将是nvarchar(max)隐式类型
  • 第二个APPLY将首先替换"整个文本中的任何内容(实际上是一行)并将其转换为 XML。
  • SELECT用于从 XML.value中获取类型安全的值。

更新:只需在INTO dbo.SomeNotExistingTableName之前添加FROM以使用此数据创建一个新表。这看起来比更新现有表更好(也可能是#-table)。我认为这是一个登台环境......

祝你好运,凌乱的数据总是让人头疼:-)

于 2021-10-01T14:50:56.440 回答
0

为什么不只是动态构建 SQL?

大概这是您要做的一次性任务,只需为您的表格运行以下内容,粘贴到 SSMS 中并运行。但如果不是,您可以构建一个自动化流程来执行它 - 当然更好的是在插入数据时正确清理!

select 
'update <table> set ' +
String_Agg(QuoteName(COLUMN_NAME) + '=Replace(' + QuoteName(column_name) + ',''"'','''')',',')
from INFORMATION_SCHEMA.COLUMNS
where table_name='<table>' and TABLE_SCHEMA='<schema>' and data_type in ('varchar','nvarchar')

示例 DB<>Fiddle

于 2021-10-01T00:06:48.750 回答