Does Bulk Insert have an opportunity with accent grave characters? - sql-server

If I do this, it works correctly with plain old varchar, so I don't think it's a nVarchar problem:
declare #RAM TABLE(
Descr Varchar(128)
)
INSERT INTO #RAM(Descr) VALUES('De La Crème')
SELECT * FROM #RAM
But I'm having trouble importing the same data with a Bulk Insert.
Q: Is there a setting that I'm missing to allow accent grave?

Your question connected not with Bulk Insert (actually, there is no Bulk Insert in your code) or INSERT, but with data types. You need to use nvarchar and N in front of the string constant which define it as a UNICODE value.
declare #RAM TABLE(
Descr nvarchar(128)
)
INSERT INTO #RAM(Descr) VALUES(N'De La Crème')
SELECT * FROM #RAM

Related

Getting ID into temp table variable on INSERT INTO ... OUTPUT ... INTO temp table

This is the sample procedure I am using.
create procedure PRO_ProcName
#description varchar(max),
#txn_no varchar
as
begin
declare #txn table (
id bigint,
description varchar(max),
txn_no varchar
);
declare #txn_id bigint;
insert into transactions
(
description,
txn_no
)
output
inserted.description,
inserted.txn_no
into #txn
values
(
#description,
#txn_no
)
select #txn_id = id from #txn;
end
I am getting an error like:
Column name or number of supplied values does not match table definition.
I know that it is because I have id field in my temporary table and it is not getting inserted in the insert into statement. I cannot give value for id because it is the auto increment primary key.
How can I tackle this situation and get id of inserted record into a variable?
The inserted table represents the data that exists in the target table after the insert - so it also includes the auto-generated values, whether they where generated by a default value definition or by an identity definition on the columns - so you need to add inserted.id to the output clause.
However, there are two more things wrong in your procedure.
The first and most important is the fact that you didn't specify a length to the #txn_no varchar parameter. SQL Server will implicitly specify the length of 1 char in this case.
The second is the fact that you are not specifying the columns list of #txn in the output clause.
Here is a improved version of your code with all these issues fixed:
create procedure PRO_ProcName
#description varchar(max),
#txn_no varchar(255) -- Note: I don't know the actual length you need
as
begin
declare #txn table (
id bigint,
description varchar(max),
txn_no varchar
);
declare #txn_id bigint;
insert into transactions
(
description,
txn_no
)
output
inserted.id,
inserted.description,
inserted.txn_no
into #txn(id, description, txn_no)
values
(
#description,
#txn_no
)
select #txn_id = id from #txn;
end
I cannot give value for id because it is the auto increment primary key.
No it isn't. You haven't declared it to be anything of the sort. So we need to fix that first:
declare #txn table (
id bigint IDENTITY PRIMARY KEY,
description varchar(max),
txn_no varchar
);
And then we fix it by specifying a column list in your INTO clause:
output
inserted.description,
inserted.txn_no
into #txn (description, txn_no)
It's always a good habit to specify column lists anyway.
Or if I've misinterpreted your question, and the id should be coming from transactions, then you just add inserted.id as another column in your OUTPUT clause. inserted represents that state of the table after the insert. So you can include columns from it in your OUTPUT clause even if you didn't specify them in the INSERT.

How to store unicode characters in SQL Server?

In SQL Server, I am trying to create a table that can store unicode characters. Specifically this one
https://www.fileformat.info/info/unicode/char/0144/index.htm
However if I pick nvarchar as the column type, then store it and then select it, it shows as a regular n.
How can I get it to store properly?
This works fine
DECLARE #t TABLE
(
InputChar NVARCHAR(10)
)
INSERT INTO #t (InputChar)
VALUES (N'ń')
INSERT INTO #t (InputChar)
VALUES ('ń')
SELECT * FROM #t
Are you making sure that when you inserting your strings you are specifying that the string is unicode ? e.g.N'yourstring'

BULK INSERT import text file

When I import a CSV or text file and bulk insert it into my database, the process successfully adds all record to the table.
My problem is that the inserted string is in Arabic, which appears as symbols in my database table. How can i solve this problem?
Insert using query
You need to choose an Arabic collation for your varchar/char columns or use Unicode (nchar/nvarchar).
CREATE TABLE MyTable
(
MyArabicColumn VARCHAR(100) COLLATE Arabic_CI_AI_KS_WS,
MyNVarCharColumn NVARCHAR(100)
)
Both columns should work.
Bulk Insert from file
This article explains how to bulk insert unicode characters.
Test Table
USE AdventureWorks2012;
GO
CREATE TABLE myTestUniCharData (
Col1 smallint,
Col2 nvarchar(50),
Col3 nvarchar(50)
);
Bulk Insert
DATAFILETYPE='widechar' allows the use of Unicode character format when bulk importing data.
USE AdventureWorks2012;
GO
BULK INSERT myTestUniCharData
FROM 'C:\myTestUniCharData-w.Dat'
WITH (
DATAFILETYPE='widechar',
FIELDTERMINATOR=','
);
GO
SELECT Col1,Col2,Col3 FROM myTestUniCharData;
GO

Client database is using Text field, I'm using nvarchar

In relation to Need to convert Text field to Varchar temporarily so that I can pass to a stored procedure
I've tried the cast, but I still get a surviving CRLF that plays havoc with my system. There is no way I can alter anything on the client, I can't even CREATE FUNCTION. I am as such not meant to alter anything on the client side, so that is all good.
Is there a way for me to remove any and all CRLF, Tabulator and other likewise ascii codes from the text field as part of a SELECT FROM script?
As far as I'm allowed to inquire the database is a SQL Server 11.0.2100
If you think about smaller set of special characters to replace/delete, you can use nested REPLACE() in your SELECT:
-- preparation of the example
CREATE TABLE #tt (id int identity (1,1), col text)
GO
INSERT INTO #tt (col) VALUES (N'this is a text
multiline
3rd line')
GO
-- run of the example
SELECT REPLACE(REPLACE(REPLACE(CAST(col as varchar(MAX)) ,
CHAR(9), '<9>'), -- replace '<9>' for '' to achieve removal
CHAR(10), '<10>'),
CHAR(13), '<13>') AS NewText
FROM #tt
--cleanup
--DROP TABLE #tt
Output:
(1 row(s) affected)
NewText
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
this is a text<13><10>multiline<13><10>3rd line
(1 row(s) affected)

Simplify SQL Insert which uses NEWSEQUNETIALID() column default

I have the following insert stored procedure:
CREATE Procedure dbo.APPL_ServerEnvironmentInsert
(
#ServerEnvironmentName varchar(50),
#ServerEnvironmentDescription varchar(1000),
#UserCreatedId uniqueidentifier,
#ServerEnvironmentId uniqueidentifier OUTPUT
)
WITH RECOMPILE
AS
-- Stores the ServerEnvironmentId.
DECLARE #APPL_ServerEnvironment TABLE (ServerEnvironmentId uniqueidentifier)
-- If #ServerEnvironmentId was not supplied.
IF (#ServerEnvironmentId IS NULL)
BEGIN
-- Insert the data into the table.
INSERT INTO APPL_ServerEnvironment WITH(TABLOCKX)
(
ServerEnvironmentName,
ServerEnvironmentDescription,
DateCreated,
UserCreatedId
)
OUTPUT Inserted.ServerEnvironmentId INTO #APPL_ServerEnvironment
VALUES
(
#ServerEnvironmentName,
#ServerEnvironmentDescription,
GETDATE(),
#UserCreatedId
)
-- Get the ServerEnvironmentId.
SELECT #ServerEnvironmentId = ServerEnvironmentId
FROM #APPL_ServerEnvironment
END
ELSE
BEGIN
-- Insert the data into the table.
INSERT INTO APPL_ServerEnvironment WITH(TABLOCKX)
(
ServerEnvironmentId,
ServerEnvironmentName,
ServerEnvironmentDescription,
DateCreated,
UserCreatedId
)
VALUES
(
#ServerEnvironmentId,
#ServerEnvironmentName,
#ServerEnvironmentDescription,
GETDATE(),
#UserCreatedId
)
END
GO
I could have simplified the above as:
CREATE Procedure dbo.APPL_ServerEnvironmentInsert
(
#ServerEnvironmentName varchar(50),
#ServerEnvironmentDescription varchar(1000),
#UserCreatedId uniqueidentifier,
#ServerEnvironmentId uniqueidentifier OUTPUT
)
WITH RECOMPILE
AS
-- Ensure #ServerEnvironmentId IS NOT NULL
SELECT ISNULL(#ServerEnvironmentId, newid())
-- Insert the data into the table.
INSERT INTO APPL_ServerEnvironment WITH(TABLOCKX)
(
ServerEnvironmentId,
ServerEnvironmentName,
ServerEnvironmentDescription,
DateCreated,
UserCreatedId
)
VALUES
(
#ServerEnvironmentId,
#ServerEnvironmentName,
#ServerEnvironmentDescription,
GETDATE(),
#UserCreatedId
)
GO
But by doing so, i loose the performance improvements of the newsequentialid() over newid(). newsequentialid() can not be set in code as newid(), it can only be supplied as a default value on a table column level.
Any ideas anyone on simplifying the original query, but utilising newsequentialid()? Or, is the original query the most simplified solution in achieving this?
Since the newsequentialid() can only be used as a column default value, you could change your original query to:
insert just the #ServerEnvironmentId if no value had been supplied, thus generating a new sequential ID and retrieving it from the OUTPUT clause
then update that row defined by either the #ServerEnvironmentId passed in originally, or the new ID you just created by inserting a "dummy row" into your table
Not sure if that would be any faster / more efficient - you would have to do some measurements on that.
Yes. Consider giving the new merge statement a try. It should be 100% compatible with the column default of newsequentialid(), and it will get the SQL down to a single concise statement. I hope this helps.
My original idea was correct. It is the simplest and most readable solution possible.

Resources