To the wonderful people at Stack who have helped me time and time again... I am trying to run a bulk insert routine for all the files in a folder. This is my approach, but I seem to have hit a roadblock with a message saying "Access is denied in my select statement"
EXEC [dbo].[procReadFolder] 'C:\Users\ABC\Downloads\NYSE_2015'
I have admin access to all the folders and files so unsure of the next step.
See Logic below:
ALTER procedure [dbo].[procReadFolder] #path sysname
as
begin
set nocount on
declare #dirContent table(
id int identity(1,1),
FileName sysname NULL
)
declare #cmd nvarchar(512)
set #cmd = 'DIR /b ' + #path
insert into #dirContent
exec master..xp_cmdshell #cmd
select * from #dirContent
-- Code to Loop through all the records in the file
-- To be written
-- Routine that takes the file name as a parameter and inserts the file
EXEC [dbo].[BulkInsert] 'Path'
end
Result Set:
1 Access is denied.
2 NULL
You will need to ensure that the account that the SQL Server Service is running as has access to the specific path.
The stored procedure is executed under the security context of the account configured to run the SQL Server Service, and therefore that is the account that will need to be given permissions to the folder on the drive.
I changed the SQL service account to another user account "SQLService" instead of the default NT/MSSQLServer account and it worked
Related
I'm trying to create a folder in the file explorer from within SQL Server Management Studio 18. Is this even possible? I know with VBA you can do it. I tried some code I found online, I even enabled xp_cmdshell and it runs but no folder is created. I tried with this code but pretty sure I'm missing something.
declare #cmdpath nvarchar(60)
set #cmdpath = 'MD '+ #Location
exec master.dbo.xp_cmdshell #cmdpath
or this one:
declare #FilePath varchar(100)
set #FilePath = 'D:\FolderTest'
EXEC master.dbo.xp_create_subdir #FilePath
SQL is a means of relating to a database. Typically queries are embedded in another file (a python script or java application for example). The job of creating files and folders falls outside the database and would not be handled by a query.
So the short answer is no. SQL is not the thing to use to make files and folders.
I have an SQL script which I want to run on multiple databases. The script runs a couple of update and insert statements and I also want to open and parse an xml file on different paths.
The issue I have is that I know where the file I want to open is (the directory) but I don't know its name (the name is random) but the extension is always .profile (which is a xml file) and there is only one file in each directory.
I wonder how I can open a XML/profile file without knowing its exact name using MS SQL.
As far as I understand your question correctly:
declare #files table (ID int IDENTITY, fileName varchar(max))
insert into #files execute xp_cmdshell 'dir <yourdirectoryhere>\*.profile /b'
declare #fileName varchar(max)
select top 1 #fineName = fileName * from #files
does what you want but is based on calling xp_cmdshell and it's usually a very bad idea to use it.
Try something along the lines of this:
DECLARE #output NVARCHAR(MAX)
CREATE TABLE #OUTPUT
(
OUTPUT VARCHAR(255) NULL
)
INSERT #OUTPUT
EXEC #output = XP_CMDSHELL
'DIR "C:\temp\*.profile" /B '
SELECT *
FROM #OUTPUT
DROP TABLE #OUTPUT
As explained here (and that's just one way), you can access disk contents from SQL Server, provided your permissions are working fine.
IIRC, the following options need to be enabled. However, you need them anyway to access files from SQL Server.
EXEC sp_configure 'show advanced options', 1
GO
RECONFIGURE
GO
EXEC sp_configure 'xp_cmdshell', 1
GO
As a proof of concept we're trying to insert an xp_cmdshell command into an existing solution. Currently an application invokes a stored procedure on our database server which when profiled looks like:
declare #P1 int
set #P1=1
exec Name_Of_The_SP #param1 = 3, #param2 = 'blah', #parametc = 'blahetc', #ID = P1 output
select #P1
The SP essentially opens a transaction, inserts a row, and then commits. Inside this we added:
exec master..xp_cmdshell 'dir > c:\test.txt'
When we then run the first block of code in a SSMS query window the file is generated on the server as expected. But when we use the application to invoke it then the rows are inserted as normal but the file isn't generated?
The SQL Server and SQLAgent users are local admins and sysadmins so can't see any issues there. Tried making the application user a local admin also, to no avail, it was already a sysadmin.
This is SQL Server 2000
We managed to figure this out - we (I) were overlooking in profiler that the exec was coming in under a different login. Granting execute permission to master.dbo.xp_cmdshell specifically got it working. Apologies to anyone who spent any time/effort on this!
I am running SQL Server 2005 on Windows Server 2003 machine.
I have a requirement to accumulate small text files into a bigger one.
So I use
exec xp_cmdshell #sql
where #sql=
'copy /b'+#sourcePath+#sourceFile+' '+#destinationPath+#NewFileName
Both the source and destination paths are on a separate server.
Seldom this process fails and I don't find anything else in the event or SQL Server logs.
The Surface Area Config for xp_cmdshell is also enabled.
Please help.....
I just tested this on my sql server 2005 and EXEC dbo.xp_cmdshell always returns output (even in the case of a bogus command) in the form of a table. For C#, if you call this code with ExecuteNonQuery, then call it with ExecuteReader and read the output. Alternatively, you could dump the output in a table so that you can look at it later at your leisure. Create a table like this :
CREATE TABLE [dbo].[xp_cmdShellOutput](
[errorMsg] [nvarchar](max) NULL
)
and then use this code :
DECLARE #sql AS VARCHAR(600)
SELECT #sql = '<your command>'
INSERT dbo.xp_cmdShellOutput(errorMsg)
EXEC dbo.xp_cmdshell #sql
I am using sqlcmd in a T-SQl script to write a text file to a network location. However SQLCMD is failing to write to that location due to access permission to the network folder. SP is being run under my user account which has access to the network folder.
Could you please help me under which account sqlcmd will run if I do not specify -U and -P option in TSQL Script?
Use this to find the user name:
PRINT Suser_Sname();
If you don't provide credentials with -u/-p it will try to use windows authentication; i.e the windows account of whomever is running it.
I often just use Process Monitor to look at what account is being used and what the permission error is.
You say you are using SQLCMD in a T-SQL script, don't you mean you are using SQLCMD to run a T-SQL script? How is your script writing a text file? Does it work in SQL Manager? My guess is that the user account SQL Server is running under doesn't have access to that location.
If you call an SQL script via xp_cmdshell without User and Password parameters it will run in the environment of the mssqlserver service, which is very much restricted, and without changing security parameters you will get mostly an 'Access is denied' message instead of the results of the script.
To avoid this security conflict situation I use the following trick in my stored procedure create_sql_proc. I read the text of the script file, and wrap it in a procedure by adding a head and a foot to it. Now I have a script creating a stored procedure from the SQL-file called #procname.
If you let now run this stored procedure by EXEC #procname, it will run in your security environment, and delivers the result you would get by running it from a command prompt:
CREATE PROCEDURE create_sql_proc(#procName sysname, #sqlfile sysname) AS
BEGIN
DECLARE #crlf nvarchar(2) = char(10)+char(13)
DECLARE #scriptText nvarchar(max)
DECLARE #cmd nvarchar(max)
= N'SET #text = (SELECT * FROM openrowset(BULK '''+#sqlFile+''', SINGLE_CLOB) as script)'
EXEC sp_executesql #cmd , N'#text nvarchar(max) output', #text = #scriptText OUTPUT
DECLARE #ProcHead nvarchar(max) = N'CREATE or ALTER PROCEDURE '+#procName+ ' AS '+#crlf+'BEGIN'+#crlf
DECLARE #ProcTail nvarchar(max) = #crlf + N'END '
SET #scriptText = #ProcHead + #scriptText + #ProcTail
-- create TestGen stored procedure --
EXEC sys.sp_executesql #scriptText
END