SQL Server : Wrong Enconding on Select with Union - sql-server

I got multiple tables, all of the same structure, containing the same columns. The columns are all varchar(250).
Now I have a query, that connects all the tables via UNION ALL and selects a column named InsertX that contains values like "134,856710602534"
My problem is: after UNIONing all the tables and selecting the InsertX column 134,856710602534 becomes 134ΒΈ856710602534. So the comma gets messed up. I tried different commands like CAST (InsertX AS varchar(250)) and Collate Latin1_General_CI_AS in the SELECT query, but nothing helps.

Are you sure it is the raw SQL that is converting that vs what is consuming it? I created the following text and it still has commas:
DECLARE #tbl1 TABLE (
COL1 VARCHAR(250)
);
DECLARE #tbl2 TABLE (
COL1 VARCHAR(250)
);
INSERT INTO #tbl1
( COL1 )
VALUES ( '134,856710602534' -- COL1 - varchar(250)
)
INSERT INTO #tbl2
( COL1 )
VALUES ( '134,856710602874' -- COL1 - varchar(250)
);
SELECT COL1
FROM #tbl1
UNION ALL
SELECT COL1
FROM #tbl2

The problem was the third-party-application...
Thank you for your help anyway!

Related

Remove the last value after a comma in nvarchar SQL

I have a column (Col1) with nvarchar(50) values like this: '17031021__,0,0.1,1'. I want to use this value to update another column(Col2), but remove the last number after the last comma (ex: '17031021__,0,0.1'). I think I need something like this:
CREATE TABLE table1 (
Col1 nvarchar(50),
Col2 nvarchar(50)
);
UPDATE table1
SET Col1 = '17031021__,0,0.1,1'
Select reverse(stuff(reverse(Col1), 1, 1, '')) As Col2
This is not quite right. What is the easiest way to achieve this?
Something along the following will give you a head-start.
SQL
-- DDL and sample data population, start
DECLARE #tbl TABLE (ID INT IDENTITY PRIMARY KEY, tokens NVARCHAR(100));
INSERT INTO #tbl (tokens) VALUES
('17031021__,0,0.1,1');
-- DDL and sample data population, end
SELECT *
, LEFT(tokens, pos) AS result
FROM #tbl
CROSS APPLY (SELECT LEN(tokens) - CHARINDEX(',', REVERSE(tokens))) AS t(pos);
And after you feel comfortable:
UPDATE #tbl
SET tokens = LEFT(tokens, LEN(tokens) - CHARINDEX(',', REVERSE(tokens)));
-- test
SELECT * FROM #tbl;
OK, the aforementioned solutions seemed like overkill, so I was able to find an easier solution that worked. Here is what I used generically:
UPDATE [dbo].[table1]
SET [Col2] = left (Col1, len(Col1) - charindex(',', reverse(Col1) + ','))
Very similar to the second solution above but with the ',' added at the end. This produced the desired result.

Get updated row as XML

Is there any way to get the last updated row as XML in sql server?
Consider this snippet
DECLARE #table TABLE (
NAME NVARCHAR(255)
,Col2 INT
)
INSERT INTO #table
VALUES (
'a1'
,1
)
INSERT INTO #table
VALUES (
'a2'
,2
)
UPDATE #table
SET NAME = 'hello'
OUTPUT inserted.*
WHERE Col2 = 2
The above statements outputs the updated row. How can I output the row as XML, as I would do with a SELECT statement?
I tried the SELECT syntax, but was unsuccessful.
UPDATE #table
SET NAME = 'hello'
OUTPUT (inserted.* FOR XML AUTO)
WHERE Col2 = 2
Is there any way to accomplish this other than writing it to a table and selecting from the table?
Is there any way to accomplish this other than writing it to a table
and selecting from the table?
Not that I know of. Create a table variable where you insert the output from the update and then use that to create the XML output you want.
DECLARE #table TABLE
(
NAME NVARCHAR(255),
Col2 INT
);
INSERT INTO #table VALUES ('a1', 1);
INSERT INTO #table VALUES ('a2', 2);
DECLARE #updateresult TABLE
(
NAME NVARCHAR(255),
Col2 INT
);
UPDATE #table
SET NAME = 'hello'
OUTPUT inserted.NAME,
inserted.Col2
INTO #updateresult(Name, Col2)
WHERE Col2 = 2
SELECT NAME, Col2
FROM #updateresult
FOR XML PATH('row');

Use same GUID twice per row

I am building an application to transfer data from an SQL server to an offsite location via ftp and XML files.
I am building the XML data for each file via a query with FOR XML PATH('path'), TYPE.
I'm going to use a GUID to generate the filename as well as use as an identiifier within the file, currently my SQL to get the table is as follows (simplified):
SELECT LVL1.inv_account_no
, LVL1.cus_postcode
, CONVERT(varchar(255),NEWID()) + '.xml' as FileName
, (SELECT (SELECT CONVERT(varchar(255),NEWID()) FOR XML PATH('ident'), TYPE), (
SELECT.... [rest of very long nested select code for generating XML]
SQL Fiddle Example
This is giving me:
Account Postcode FileName xCol
AD0001 B30 3HX 2DF21466-2DA3-4D62-8B9B-FC3DF7BD1A00 <ident>656700EA-8FD5-4936-8172-0135DC49D200</ident>
AS0010 NN12 8TN 58339997-8271-4D8C-9C55-403DE98F06BE <ident>78F8078B-629E-4906-9C6B-2AE21782DC1D</ident>
Basically different GUID's for each row/use of NEWID().
Is there a way I can insert the same GUID into both columns without incrementing a cursor or doing two updates?
Try something like this:
SELECT GeneratedGuid, GeneratedGuid
FROM YourTable
LEFT JOIN (SELECT NEWID() AS GeneratedGuid) AS gg ON 1 = 1
"GeneratedGuid" has a different GUID for every row.
You could use a Common Table Expression to generate the NEWID for each resulting row.
Here is the SQL Fiddle : http://www.sqlfiddle.com/#!3/74c0c/1
CREATE TABLE TBL (
ID INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
GCOL VARCHAR(255),
XCOL XML)
create table tbl2 (
id int identity(1,1) not null primary key,
foo int not null )
insert into tbl2 (foo) values
(10),(20),(30)
; WITH cte_a as ( select NEWID() as ID )
INSERT INTO TBL
SELECT CONVERT(varchar(255),cte_a.ID )
, (SELECT CONVERT(varchar(255),cte_a.ID) FOR XML PATH('Output'), TYPE)
from tbl2, cte_a
Create a temporary variable and assign a NEWID() to it. Then you can use this variable as many times in your SELECT or INSERT queries. Value of temporary variable remain same till it's scope. In following example #gid is a temporary variable and assigned a GUID value as VARCHAR(36)
DECLARE #gid varchar(36)
SET #gid = CAST(NEWID() AS VARCHAR(36))
INSERT INTO [tableName] (col1, col2) VALUES(#gid, #gid)
after executing the above query col1 and col2 from [tablename] will have same guid value.

Insert from single table into multiple tables, invalid column name error

I am trying to do the following but getting an "Invalid Column Name {column}" error. Can someone please help me see the error of my ways? We recently split a transaction table into 2 tables, one containing the often updated report column names and the other containing the unchanging transactions. This leave me trying to change what was a simple insert into 1 table to a complex insert into 2 tables with unique columns. I attempted to do that like so:
INSERT INTO dbo.ReportColumns
(
FullName
,Type
,Classification
)
OUTPUT INSERTED.Date, INSERTED.Amount, INSERTED.Id INTO dbo.Transactions
SELECT
[Date]
,Amount
,FullName
,Type
,Classification
FROM {multiple tables}
The "INSERTED.Date, INSERTED.Amount" are the source of the errors, with or without the "INSERTED." in front.
-----------------UPDATE------------------
Aaron was correct and it was impossible to manage with an insert but I was able to vastly improve the functionality of the insert and add some other business rules with the Merge functionality. My final solution resembles the following:
DECLARE #TransactionsTemp TABLE
(
[Date] DATE NOT NULL,
Amount MONEY NOT NULL,
ReportColumnsId INT NOT NULL
)
MERGE INTO dbo.ReportColumns AS Trgt
USING ( SELECT
{FK}
,[Date]
,Amount
,FullName
,Type
,Classification
FROM {multiple tables}) AS Src
ON Src.{FK} = Trgt.{FK}
WHEN MATCHED THEN
UPDATE SET
Trgt.FullName = Src.FullName,
Trgt.Type= Src.Type,
Trgt.Classification = Src.Classification
WHEN NOT MATCHED BY TARGET THEN
INSERT
(
FullName,
Type,
Classification
)
VALUES
(
Src.FullName,
Src.Type,
Src.Classification
)
OUTPUT Src.[Date], Src.Amount, INSERTED.Id INTO #TransactionsTemp;
MERGE INTO dbo.FinancialReport AS Trgt
USING (SELECT
[Date] ,
Amount ,
ReportColumnsId
FROM #TransactionsTemp) AS Src
ON Src.[Date] = Trgt.[Date] AND Src.ReportColumnsId = Trgt.ReportColumnsId
WHEN NOT MATCHED BY TARGET And Src.Amount <> 0 THEN
INSERT
(
[Date],
Amount,
ReportColumnsId
)
VALUES
(
Src.[Date],
Src.Amount,
Src.ReportColumnsId
)
WHEN MATCHED And Src.Amount <> 0 THEN
UPDATE SET Trgt.Amount = Src.Amount
WHEN MATCHED And Src.Amount = 0 THEN
DELETE;
Hope that helps someone else in the future. :)
Output clause will return values you are inserting into a table, you need multiple inserts, you can try something like following
declare #staging table (datecolumn date, amount decimal(18,2),
fullname varchar(50), type varchar(10),
Classification varchar(255));
INSERT INTO #staging
SELECT
[Date]
,Amount
,FullName
,Type
,Classification
FROM {multiple tables}
Declare #temp table (id int, fullname varchar(50), type varchar(10));
INSERT INTO dbo.ReportColumns
(
FullName
,Type
,Classification
)
OUTPUT INSERTED.id, INSERTED.fullname, INSERTED.type INTO #temp
SELECT
FullName
,Type
,Classification
FROM #stage
INSERT into dbo.transacrions (id, date, amount)
select t.id, s.datecolumn, s.amount from #temp t
inner join #stage s on t.fullname = s.fullname and t.type = s.type
I am fairly certain you will need to have two inserts (or create a view and use an instead of insert trigger). You can only use the OUTPUT clause to send variables or actual inserted values ti another table. You can't use it to split up a select into two destination tables during an insert.
If you provide more information (like how the table has been split up and how the rows are related) we can probably provide a more specific answer.

contains search over a table variable or a temp table

i'm trying to concatenate several columns from a persistent table into one column of a table variable, so that i can run a contains("foo" and "bar") and get a result even if foo is not in the same column as bar.
however, it isn't possible to create a unique index on a table variable, hence no fulltext index to run a contains.
is there a way to, dynamically, concatenate several columns and run a contains on them? here's an example:
declare #t0 table
(
id uniqueidentifier not null,
search_text varchar(max)
)
declare #t1 table ( id uniqueidentifier )
insert into
#t0 (id, search_text)
select
id,
foo + bar
from
description_table
insert into
#t1
select
id
from
#t0
where
contains( search_text, '"c++*" AND "programming*"' )
You cannot use CONTAINS on a table that has not been configured to use Full Text Indexing, and that cannot be applied to table variables.
If you want to use CONTAINS (as opposed to the less flexible PATINDEX) you will need to base the whole query on a table with a FT index.
You can't use full text indexing on a table variable but you can apply the full text parser. Would something like this do what you need?
declare #d table
(
id int identity(1,1),
testing varchar(1000)
)
INSERT INTO #D VALUES ('c++ programming')
INSERT INTO #D VALUES ('c# programming')
INSERT INTO #D VALUES ('c++ books')
SELECT id
FROM #D
CROSS APPLY sys.dm_fts_parser('"' + REPLACE(testing,'"','""') + '"', 1033, 0,0)
where display_term in ('c++','programming')
GROUP BY id
HAVING COUNT(DISTINCT display_term)=2
NB: There might well be a better way of using the parser but I couldn't quite figure it out. Details of it are at this link
declare #table table
(
id int,
fname varchar(50)
)
insert into #table select 1, 'Adam James Will'
insert into #table select 1, 'Jain William'
insert into #table select 1, 'Bob Rob James'
select * from #table where fname like '%ja%' and fname like '%wi%'
Is it something like this.

Resources