0

I know this is late to the game, but we're just upgrading to Sql Server 2019 after years and years on 2008.

I started using the Latin1_General_100_CI_AI_SC_UTF8 collation as an experiment and at least on my local server it looked like it was working well.

The problem came in when we replicated the database to another server - it appears that replication is converting the text to 1252 literally, so a line of text that says

St. Joseph’s Medical Center awarded $4M to expand NICU, pediatric unit

in my database comes out as

St. Joseph’s Medical Center awarded $4M to expand NICU, pediatric unit

in the subscriber database - even though the destination table has Latin1_General_100_CI_AI_SC_UTF8 as the collation on the column.

Is there some special option one needs to set on the publication to preserve the encoding in transfer?

Thanks

EDITS: Publisher is on Sql Server 15.0.4249.2, the subscriber is on 15.0.4280.7. It's a Transactional publication using the publisher's distribution database.

EDIT2: Last week I made a test table using NVARCHAR instead, and that replicated successfully where utf-8 didn't

7
  • Are you using a distributor in your replication topology?
    – Dan Guzman
    Commented Oct 17, 2023 at 18:48
  • Not that I'm aware of. I wasn't involved in the configuration of the replication. Commented Oct 17, 2023 at 19:06
  • Sorry to be so long getting back to this. YES we are using a distributor, and the default collation on the publishing server is SQL_Latin1_General_CP1_CI_AI. Is the distribution database messing with the data being replicated? Commented Oct 24, 2023 at 13:56
  • Could you check that the distributor database collation is OK?
    – Milan
    Commented Nov 2, 2023 at 8:54
  • Thanks for responding. The default collation for the server is SQL_Latin1_General_CP1_CI_AI, so I assume that's what the collation would be for the distribution and temp databases. But I'd read other posts that said the distribution database (presumably to handle all types of data) generally used varbinary for the intermediate data housing. I've run into the case where you have to drop COLLATE clauses in a number of places when the tempdb is not in the same collation as a give table/column, but I didn't think the distribution database would have that Achilles heel Commented Nov 2, 2023 at 13:51

1 Answer 1

0

Question:
"Is there some special option one needs to set on the publication to preserve the encoding in transfer?"

Answer:
There is an option on Publication side to check:
"Publication properties -> Articles -> Article properties -> Copy collation (True / False)".
Explanation: "Copy collation: Determines wheter to copy collation settings to the destination object."

Image:
Image of Publication article Copy collation settings

Additional answer:
As an answer to your EDIT 2:
"EDIT2: Last week I made a test table using NVARCHAR instead, and that replicated successfully where utf-8 didn't"

here is an example query for demonstrating the use of UTF-8 collations for unicode characters in varchar columns.
It could better explain why the NVARCHAR column is successfully replicated in your case.

-- Example Query:  
DECLARE @Data TABLE (
    varchar_nonutf8 VARCHAR(100) COLLATE Latin1_General_100_CI_AS_SC
    , varchar_utf8 VARCHAR(100) COLLATE Latin1_General_100_CI_AS_SC_UTF8
    , nvarchar_nonutf8 NVARCHAR(100) COLLATE Latin1_General_100_CI_AS_SC
    , nvarchar_utf8 NVARCHAR(100) COLLATE Latin1_General_100_CI_AS_SC_UTF8
);

-- unicode characters exist in this string ("разуме" is Serbian for "understands")
DECLARE @Value NVARCHAR(MAX) = N'SQL2019 разуме UTF8'

INSERT INTO @Data (varchar_nonutf8, varchar_utf8, nvarchar_nonutf8, nvarchar_utf8)
VALUES (@Value, @Value, @Value, @Value)

SELECT * FROM @Data  

Query result:
Image of query result

Additional answer 1:

You should set collation on distribution database, which allows accepting correct data (it can be _UTF8 one also).

Another thing to check is the CALL/SCALL usage on Publication side:
Find it in: "Publication properties -> Articles -> Article properties -> Statement Delivery".
More explanations can be found here (blogged by Bartosz Lewandowski)

Example Image:
CALL/SCALL usage image

Additional answer 2:

Use this script to browse replication commands and find the commands and check if the problematic strings exist.
(script taken from Bartosz Lewandowski here)

--BROWSE REPL COMMANDS

declare @publisher_db nvarchar(150)
declare @publisher_db_id int
declare @seqno nvarchar(500)
declare @seqno_bin varbinary(16)
declare @error_id int
declare @error_txt nvarchar(1000)
declare @command_id int


/*-----------------PARAMETERS---------------------*/
set @publisher_db='<Published db>'
set @seqno_bin=<LSN>
set @seqno='<LSN>'
set @command_id = <command id> -- Leave NULL if all you want to get ALL commands
/*-----------------------------------------------*/

create table #temp_commands (
xact_seqno    varbinary(16) NULL,                    
originator_srvname   varchar(100) NULL,
originator_db        varchar(100) NULL,
article_id           int NULL,
type                  int NULL,
partial_command         bit NULL,
hashkey                 int NULL,
originator_publication_id  int NULL,
originator_db_version      int NULL,
originator_lsn         varbinary    (16) NULL,
command                 nvarchar   (1024) NULL,
command_id              int NULL)

select @publisher_db_id=id  
from mspublisher_databases where publisher_db=@publisher_db
select @error_id=error_id  
from msdistribution_history where xact_seqno=@seqno_bin
select top 1 @error_txt=error_text  
from  dbo.MSrepl_errors where id = @error_id

insert into #temp_commands
exec sp_browsereplcmds 
@xact_seqno_start=@seqno,
@xact_seqno_end=@seqno,
@publisher_database_id=@publisher_db_id

if @command_id is NULL
BEGIN
    select command,command_id, @error_txt as 'Error'  
    from #temp_commands order by command_id
END
ELSE
BEGIN
    select command,command_id, @error_txt as 'Error'  
    from #temp_commands where command_id=@command_id  
    order by command_id
END
drop table #temp_commands
2
  • Thank you for taking the time to respond. I did check the article properties, and "Copy collation" is, indeed, set to true. Looking at both the publisher and subscriber tables, both had the collation of the columns in question set to utf8 - yet the values in the subscriber have the 3 utf-8 bytes separated and taken literally for some reason. Commented Nov 2, 2023 at 13:46
  • On the second point, I understand how the collations are supposed to operate locally to a table and how the underlying data is getting represented. My puzzlement is specific to replication. I have a publisher table with a column declared as utf8 and a subscriber table with the same column declared as utf8, but getting the data from here to there via replication ends up with a mistranslation of the data. Commented Nov 2, 2023 at 13:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.