Stored Procedure to import data into SQL Server database... Error - sql

I have a text file file1.txt in the below format. Column 1 is AGUSR1 & Column 2 is AGUSR2. There are 3 records in the file:
"AGUSR1"|"AGUSR2"
"JASON "|"DEBBIE "
"JOY "|"JASON "
"ANNA "|"JOHN "
I have written a stored procedure to upload this text file into a SQL Server database like this:
CREATE PROCEDURE sp_Import
#TableName varchar(200),
#FilePath varchar(200)
AS
DECLARE #SQL varchar(5000)
SET #SQL = 'BULK INSERT ' + #TableName + ' FROM ''' + #FilePath +
''' WITH (FIELDTERMINATOR = ''|'', ROWTERMINATOR = ''{CR}{LF}'')'
EXEC (#SQL)
To execute it, I have used this statement:
EXEC sp_Import '[DB_DEMO].[dbo].[file1]' , '\\kacl1tsp048\DEMO\file1.txt'
Note : kacl1tsp048 is a remote server the input text file is at.
On execution, I am getting the below error -
Msg 4863, Level 16, State 1, Line 1
Bulk load data conversion error (truncation) for row 1, column 2 (AGUSR2).
The import into table schema is
CREATE TABLE [dbo].[file1]
(
[AGUSR1] [varchar](10) NULL,
[AGUSR2] [varchar](10) NULL
)

For ad-hoc style data imports I sometimes dispense with using BULK INSERTS in favor of selecting from the file itself to then process it. You could do something similar by creating a procedure to read your file as a table:
CREATE FUNCTION [dbo].[uftReadfileAsTable]
(
#Path VARCHAR(255),
#Filename VARCHAR(100)
)
RETURNS
#File TABLE
(
[LineNo] int identity(1,1),
line varchar(8000))
AS
BEGIN
DECLARE #objFileSystem int
,#objTextStream int,
#objErrorObject int,
#strErrorMessage Varchar(1000),
#Command varchar(1000),
#hr int,
#String VARCHAR(8000),
#YesOrNo INT
select #strErrorMessage='opening the File System Object'
EXECUTE #hr = sp_OACreate 'Scripting.FileSystemObject' , #objFileSystem OUT
if #HR=0 Select #objErrorObject=#objFileSystem, #strErrorMessage='Opening file "'+#path+'\'+#filename+'"',#command=#path+'\'+#filename
if #HR=0 execute #hr = sp_OAMethod #objFileSystem , 'OpenTextFile'
, #objTextStream OUT, #command,1,false,0--for reading, FormatASCII
WHILE #hr=0
BEGIN
if #HR=0 Select #objErrorObject=#objTextStream,
#strErrorMessage='finding out if there is more to read in "'+#filename+'"'
if #HR=0 execute #hr = sp_OAGetProperty #objTextStream, 'AtEndOfStream', #YesOrNo OUTPUT
IF #YesOrNo<>0 break
if #HR=0 Select #objErrorObject=#objTextStream,
#strErrorMessage='reading from the output file "'+#filename+'"'
if #HR=0 execute #hr = sp_OAMethod #objTextStream, 'Readline', #String OUTPUT
INSERT INTO #file(line) SELECT #String
END
if #HR=0 Select #objErrorObject=#objTextStream,
#strErrorMessage='closing the output file "'+#filename+'"'
if #HR=0 execute #hr = sp_OAMethod #objTextStream, 'Close'
if #hr<>0
begin
Declare
#Source varchar(255),
#Description Varchar(255),
#Helpfile Varchar(255),
#HelpID int
EXECUTE sp_OAGetErrorInfo #objErrorObject,
#source output,#Description output,#Helpfile output,#HelpID output
Select #strErrorMessage='Error whilst '
+coalesce(#strErrorMessage,'doing something')
+', '+coalesce(#Description,'')
insert into #File(line) select #strErrorMessage
end
EXECUTE sp_OADestroy #objTextStream
-- Fill the table variable with the rows for your result set
RETURN
END
Now you have a proc to convert your file to a table. You would still have to deal with the formatting of your delimiters so you could run something like this to populate [dbo].[file1]:
;WITH Split_Names (Value,Name, xmlname)
AS
(
SELECT
[LineNo],
line,
CONVERT(XML,'<Lines><line>'
+ REPLACE(line,'"|"', '</line><line>') + '</line></Lines>') AS xmlname
from [dbo].[uftReadfileAsTable]('\\kacl1tsp048\DEMO\file1.txt')
where line not like '"AGUSR1"%'
)
SELECT
Value,
RTRIM(REPLACE(xmlname.value('/Lines[1]/line[1]','varchar(100)'),'"', '')) AS AGUSR1,
RTRIM(REPLACE(xmlname.value('/Lines[1]/line[2]','varchar(100)'),'"', '')) AS AGUSR2
INTO [dbo].[file1]
FROM Split_Names
Hope that helps a little?!

Related

SQL Server Export Blob Corrupts All Files

I am exporting blobs with this code:
sp_configure 'Ole Automation Procedures', 1;
GO
RECONFIGURE;
GO
DECLARE #outout_path varchar(50) = 'D:\blob',
#i bigint,
#init int,
#data varbinary(max),
#file_path varchar(max),
#folder_path varchar(max)
DECLARE #Doctable TABLE (id int identity(1,1) , [FileName] varchar(100), file_data varBinary(max) )
INSERT INTO #Doctable([FileName],file_data)
Select top 10 thefilename, file_data FROM schm.table_with_blobs
SELECT #i = COUNT(1) FROM #Doctable
WHILE #i >= 1
BEGIN
SELECT #data = [file_data],
#file_path = #outout_path + '\'+ cast(id as varchar) + '\' + [FileName],
#folder_path = #outout_path + '\'+ cast(id as varchar)
FROM #Doctable
WHERE id = #i
EXEC [dbo].[CreateFolder] #folder_path
EXEC sp_OACreate 'ADODB.Stream', #init OUTPUT;
EXEC sp_OASetProperty #init, 'Type', 1;
EXEC sp_OAMethod #init, 'Open';
EXEC sp_OAMethod #init, 'Write', NULL, #data;
EXEC sp_OAMethod #init, 'SaveToFile', NULL, #file_path, 2;
EXEC sp_OAMethod #init, 'Close';
EXEC sp_OADestroy #init;
print 'Document Generated at - '+ #file_path
SELECT #data = NULL,
#init = NULL,
#file_path = NULL,
#folder_path = NULL;
SET #i -= 1;
END
All the files are exported as expected with the proper file format. However, all of the files are corrupted and cannot be opened, regardless of file format. What can I tweak to avoid this? Do I need to more explicitly call out the file type (available in thefilename field)?
I had a similar problem but was exporting with BCP rather than using ADODB.
I had to do two things :
convert the varbinary to varchar or nvarchar
make BCP export as
RAW
This is the BCP solution I came up with:
Declare #patient int, #mincount int, #maxcount int,#filename varchar(200), #script varchar(2000),#fileid varchar(10)
Set #patient=2;
set #mincount=1;
Declare #mydocs as table
(filename varchar(255), filebody image, drank int, file_id int)
insert into #mydocs
Select taf.Attachment_File_Name, taf.Attachment_File_Body, DENSE_RANK() OVER (ORDER BY taf.attachment_file_id) as drank, taf.Attachment_File_ID FROM [CNGSTT].[dbo].[tblAttachment] ta
left join [CNGSTT].[dbo].[tblAttachmentFile] taf
on taf.Attachment_ID=ta.Attachment_ID where ta.Patient_ID=#patient
Set #maxcount=(select MAX(drank) from #mydocs)
WHILE #mincount<=#maxcount
BEGIN
Set #filename = (select fle.FileName from #mydocs fle where drank=#mincount)
Set #fileid =(select fle.File_id from #mydocs fle where drank=#mincount)
set #script = 'bcp "SELECT cast(cast(Attachment_File_Body as varbinary(max)) as varchar(max)) from [tblattachmentfile] fle where Attachment_File_ID='+#fileid+'" queryout D:\temp\' + #filename + ' -T -c -C RAW'
exec master..xp_cmdshell #script
Set #mincount=#mincount+1
END

SQL Server 2017 - Database mail stored procedure

I have a stored procedure which basically I want to do the following:
Create temp table (if not exists) and populate with data
Output the query to SSMS, and assigning the query a variable (#sql)
Using the query, e-mail the contents of the query to the recipients
My script is this:
Create Procedure ListDaysofYear(#year as integer)
as
Declare #sql as varchar(200), #DBqry as varchar(200),
#tab as char(1) = char(9)
Declare #dayofyear as bigint = 1
Declare #monthofyear as int = 1
Declare #day as int = 1
Declare #curDate as datetime
Declare #DB as varchar(40)
Declare #sql2 as varchar(40)
Set #curDate = datefromparts(#year, #monthofyear, #day)
Set #DB = 'msdb'
IF OBJECT_ID('tempdb.dbo.##daysofYear','U') IS NOT NULL
DROP TABLE ##daysofYear
--Print 'YES'
ELSE
CREATE TABLE ##daysofYear
(
cDate DATETIME PRIMARY KEY NOT NULL,
cMonth VARCHAR(20) NOT NULL,
cDay VARCHAR(20) NOT NULL
)
WHILE year(#curDate) = #year
BEGIN
-- Insert rows based on each day of the year
INSERT INTO ##daysofYear (cDate, cMonth, cDay)
VALUES( (#curDate),
(DATENAME([MONTH], #curDate)),
(DATENAME([WEEKDAY], #curDate)) )
SET #curDate = #curDate + 1
END
--Output file to SSMS query window
Select dy.* from ##daysofYear dy;
Set #sql = 'Select dy.* from ##daysofYear dy;'
Set #sql2 = 'Use ' + #DB + '; Exec msdb.dbo.sp_send_dbmail
#profile_name = ''Notifications'',
#recipients = ''mikemirabelli6#hotmail.com'',
#attach_query_result_as_file = 1,
#query_attachment_filename = ''daysofyear.txt'',
#query_result_separator = '',
#body = ''The attached output file - DaysofYear table'',
#query = ''Select dy.* from ##daysofYear dy'' ;'
--Execute sp_sqlexec #sql
Exec(#sql2)
Basically when I run the execute line:
Exec dbo.ListDaysofYear 2018 ;
I get the following message the first time:
Msg 208, Level 16, State 0, Procedure dbo.ListDaysofYear, Line 25
[Batch Start Line 52] Invalid object name '##daysofYear
I believe it’s related to the "DROP TABLE" part of the T-SQL.
Thanks
Think i found the issue:
IF OBJECT_ID('tempdb.dbo.##daysofYear','U') IS NOT NULL <-- here you are dropping the table if exisit but doesn't create it so it throws an error in line 25 where it tries to insert data (to a table you dropped). i suggest replacing drop table with TRUNCATE TABLE.

Insert procedure with 2 string parameters

I wrote this procedure to insert 2 string variables into a table:
ALTER Procedure
[dbo].[IND] (#VAssetID varchar(50), #UAssetID nvarchar(255))
As
BEGIN
Declare #Query1 as varchar(max)
Set #Query1 =
'Insert into IndMatch(V_AssetID,U_AssetID) values('+ #VAssetID +','+#UAssetID+')'
EXECUTE(#Query1)
END
When I run the procedure with number strings only it works fine as soon as I try and insert alphanumeric codes the procedure fails.
When the procedure executes with numbers strings only:
Exec IND #VAssetID = '231243332', #UAssetID = '21343321'
The procedure executes fine with and inserts the values into the table.
When the procedure executes with alphanumeric strings:
Exec IND #VAssetID = '2312I43332', #UAssetID = '21T343R321'
It generates the error:
Incorrect syntax near 'I43332'.
Please assist
Why execute as a string? This'll work just fine:
ALTER Procedure [dbo].[IND] (#VAssetID varchar(50), #UAssetID nvarchar(255))
As
BEGIN
Insert into IndMatch(V_AssetID,U_AssetID) values(#VAssetID, #UAssetID)
END
you are missing the [ ' ] around the values.
It will try to execute an insert like so:
Insert into IndMatch(V_AssetID,U_AssetID) values(2312I43332,21T343R321 )
but the correct syntax should be
Insert into IndMatch(V_AssetID,U_AssetID) values('2312I43332','21T343R321' )
you need to do this:
ALTER Procedure
[dbo].[IND] (#VAssetID varchar(50), #UAssetID nvarchar(255))
As
BEGIN
Declare #Query1 as varchar(max)
Set #Query1 =
'Insert into IndMatch(V_AssetID,U_AssetID) values('''+ #VAssetID +''','''+#UAssetID+''')'
EXECUTE(#Query1)
END
Run this and this should explain it:
DECLARE #Query1 VARCHAR(MAX), #VAssetID VARCHAR(50), #UAssetID NVARCHAR(255);
SET #VAssetID = '231243332';
SET #UAssetID = '21343321';
SET #Query1 = 'Insert into IndMatch(V_AssetID,U_AssetID) values('+#VAssetID+','+#UAssetID+')';
PRINT #Query1;
SET #Query1 = 'Insert into IndMatch(V_AssetID,U_AssetID) values('''+#VAssetID+''','''+#UAssetID+''')';
PRINT #Query1;
PRINT RESULT:
Better yet you can do this as I don't see a need for dynamic sql here:
ALTER Procedure
[dbo].[IND] (#VAssetID varchar(50), #UAssetID nvarchar(255))
As
BEGIN
Insert into IndMatch(V_AssetID,U_AssetID) values( #VAssetID , #UAssetID )
END

Incorrect syntax near '.'

I am trying to run a stored procedure in SQL Server 2008. After I created the procedure, I selected the option to "Script Table AS EXECUTE", which (after entering the SELECT queries for the field names) comes up as:
DECLARE #RC int
DECLARE #tablename varchar(50)
DECLARE #field1 varchar(25)
DECLARE #field2 varchar(25)
SELECT #tablename = '[databasename].[dbo].[tablename]'
SELECT #field1 = 'name'
SELECT #field2 = 'amount'
EXECUTE #RC = [databasename].[dbo].[procedurename]
#tablename
,#field1
,#field2
GO
I then get the following error:
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near '.'
but there doesn't appear to be any '.' anywhere near line 1 or anywhere other than the table names?
Nothing is wrong with that code. As it stated in the comment that something is wrong with your stored procedure. Take the source code of the procedure, delete lines with create/alter and the input parameters until the first begin. After that remove the last END. Replace all the parameters in the code and execute it as normal TSQL statement. In that case you'll easily find where it is failing.
Just to be sure that your code is working, execute following script:
CREATE PROCEDURE [procedurename]
#tablename VARCHAR(1000)
,#field1 VARCHAR(1000)
,#field2 VARCHAR(1000)
AS
BEGIN
SELECT 1
END
GO
DECLARE #RC int
DECLARE #tablename varchar(50)
DECLARE #field1 varchar(25)
DECLARE #field2 varchar(25)
SELECT #tablename = '[databasename].[dbo].[tablename]'
SELECT #field1 = 'name'
SELECT #field2 = 'amount'
EXECUTE #RC = [dbo].[procedurename]
#tablename
,#field1
,#field2
GO
DROP PROCEDURE [procedurename]
GO

Pass a TABLE variable to sp_executesql

I'm trying to pass a TABLE variable to the sp_executesql procedure:
DECLARE #params NVARCHAR(MAX)
SET #params = '#workingData TABLE ( col1 VARCHAR(20),
col2 VARCHAR(50) )'
EXEC sp_executesql #sql, #params, #workingData
I get the error:
Msg 156, Level 15, State 1, Line 1
Incorrect syntax near the keyword 'TABLE'.
I tried omitting the column specification after 'TABLE'. I also tried to declare the table as a variable inside the dynamic SQL. But no luck...
Seems to me that TABLE variables aren't allowed to be passed as parameters in this procedure?. BTW: I'm running MSSQL2008 R2.
I'm not interested in using a local temp table like #workingData because I load the working data from another procedure:
INSERT INTO #workingData
EXEC myProc #param1, #param2
Which I cannot do directly into a temp varaible (right?)...
Any help appreciated!
If you are using SQL Server 2008, to pass a table variable to a stored procedure you must first define the table type, e.g.:
CREATE TYPE SalesHistoryTableType AS TABLE
(
[Product] [varchar](10) NULL,
[SaleDate] [datetime] NULL,
[SalePrice] [money] NULL
)
GO
or use an existing table type stored in the database.
Use this query to locate existing table types
SELECT * FROM sys.table_types
To use in an stored procedure, declare an input variable to be the table:
CREATE PROCEDURE usp_myproc
(
#TableVariable SalesHistoryTableType READONLY
)
AS BEGIN
--Do stuff
END
GO
Populate the table variable before passing to the stored procedure:
DECLARE #DataTable AS SalesHistoryTableType
INSERT INTO #DataTable
SELECT * FROM (Some data)
Call the stored procedure:
EXECUTE usp_myproc
#TableVariable = #DataTable
Further discussions here.
OK, this will get me what I want, but surely isn't pretty:
DECLARE #workingData TABLE ( col1 VARCHAR(20),
col2 VARCHAR(20) )
INSERT INTO #workingData
EXEC myProc
/* Unfortunately table variables are outside scope
for the dynamic SQL later run. We copy the
table to a temp table.
The table variable is needed to extract data directly
from the strored procedure call above...
*/
SELECT *
INTO #workingData
FROM #workingData
DECLARE #sql NVARCHAR(MAX)
SET #sql = 'SELECT * FROM #workingData'
EXEC sp_executesql #sql
There must be a better way to pass this temporary resultset into sp_executesql!?
Regards
Alex
While this may not directly answer your question, it should solve your issue overall.
You can indeed capture the results of a Stored Procedure execution into a temporary table:
INSERT INTO #workingData
EXEC myProc
So change your code to look like the following:
CREATE TABLE #workingData ( col1 VARCHAR(20),
col2 VARCHAR(20) )
INSERT INTO #workingData
EXEC myProc
DECLARE #sql NVARCHAR(MAX)
SET #sql = 'SELECT * FROM #workingData'
EXEC sp_executesql #sql
Regards,
Tim
Alter PROCEDURE sp_table_getcount
#tblname nvarchar(50) ,
#totalrow int output
AS
BEGIN
Declare #params nvarchar(1000)
Declare #sql nvarchar(1000)
set #sql = N'Select #cnt= count(*) From #tbl'
set #params = N'#tbl nvarchar(50) , #cnt int OUTPUT'
Exec sp_executesql #sql , #params ,#tbl=#tblname , #cnt = #totalrow OUTPUT
END
GO
Please note that the above code will not work as table as a object is out of the scope.It will give you the error: must declare table variable.In order to work around we can do the following.
Alter PROCEDURE sp_table_getcount
#tblname nvarchar(50) ,
#totalrow int output
AS
BEGIN
Declare #params nvarchar(1000)
Declare #sql nvarchar(1000)
set #sql = N'Select #cnt= count(*) From dbo.' + #tblname
set #params = N'#cnt int OUTPUT'
Exec sp_executesql #sql , #params , #cnt = #totalrow OUTPUT
END
GO
So-called TableType is tricky. #Alex version should work. However, to simplify and faster performance, go check sys.tables for matching table name while not compromise security and performance.
Here it is
create proc [dbo].Test11
#t1 AS nvarchar(250), #t2 nvarchar(250)
AS
BEGIN
SET nocount ON;
DECLARE #query AS nvarchar(MAX)
if exists (select * from sys.tables where name = #t1) and
exists (select * from sys.tables where name = #t2)
begin
SET #query = N'select * FROM '+ #t1 + N' join ' + #t2 + N' ON ...' ;
select 'Safe and fast'
print #query
exec sp_executesql #query
end
else
select 'Bad, no way Jose.'
SET nocount OFF;
END
GO