• When using values of multiple types, SQL Server will always use Data Type Precedence (Transact-SQL). As you can see, INT is higher in the list than VARCHAR, so INT takes precendence. We both know that 'b' and 'd' aren't integers, so the conversion fails.

    When using your for xml path, all the values are returning in a single column and a column CANNOT have fields of different types. Therefore Precedence applies. YOu're data would actually look like this:

    v

    ---

    1

    b

    3

    d

    Considering that 1 and 3 are of datatype INT, and 'b' and 'd' are VARCHARs, that table can't exist.

    This, instead, would work for you:

    DROP TABLE tmp.foo

    CREATE TABLE tmp.foo (

    id INT IDENTITY(1, 1) NOT NULL,

    a TINYINT,

    b VARCHAR(1),

    c TINYINT,

    d VARCHAR(1)

    PRIMARY KEY (id)

    );

    -- single row so NULLs have no bearing on the error

    INSERT INTO tmp.foo (a, b, c, d) VALUES (1, 'b', 3, 'd');

    SELECT

    id,

    a,b,c,d,

    bar = STUFF(

    (

    SELECT '-' + v

    FROM (VALUES (CAST(a AS VARCHAR(MAX))), (CAST(b AS VARCHAR(MAX))), (CAST( c AS VARCHAR(MAX))), (CAST(d AS VARCHAR(MAX)))) AS v (v)

    FOR XML PATH (''), TYPE

    ).value('.[1]', 'varchar(max)'),

    1, 1, ''

    )

    FROM tmp.foo

    ORDER BY id;

    Thom~

    Excuse my typos and sometimes awful grammar. My fingers work faster than my brain does.
    Larnu.uk