Determine ODBC database driver from TADOConnection object? - sql-server

Using Delphi 7 with ADO objects, is it possible to determine the ODBC database driver from the TADOConnection object? So detect whether it is MS-Access or SQL Server or Oracle etc.
The program connects to a database by just using the name of an ODBC data source, and I want to determine whether that database is an MS-Access database or SQL Server. I want to do this because MS-Access and SQL Server use different SQL function names to cast an integer to a string.
The application builds an SQL string which retrieves the VERSION of some configuration objects. It works for SQL server using cast(), but I also want to support MS-Access which uses CStr():
SELECT NAME + '_' + CAST(VERSION as varchar) as OBJECT_NAME FROM ANALYSIS // SQL Server
SELECT NAME + '_' + CStr(VERSION) as OBJECT_NAME FROM ANALYSIS // MS-Access
I've tried looking at the TADOConnection.Provider but that is MSDASQL.1 in both cases.
if (myqry.Connection.Provider = 'MSDASQL.1') then
strSQL := strSQL + 'cast(' + myfieldname + ' as varchar)' // always goes here..
else
strSQL := strSQL + 'CStr(' + myfieldname + ')'; // ..never to here
I've looked at all the TADOConnection properties, but I'm starting to suspect it's not possible. Any ideas how to solve this?

ODBC is designed to abstract away the implementation details of the server. You can use ODBC specific syntax that will be translated to a statement of the appropriate SQL flavour for the server. Here you can substitute :
... { fn CONVERT( VERSION, SQL_VARCHAR ) } AS OBJECT_NAME FROM ANALYSIS
These substitutions are known as ODBC Escape Sequences and can be substituted in queries where there are vendor-specific syntax differences.

Related

Why does SQL Server HASHBYTES work differently from Oracle STANDARD_HASH?

Any idea why the two hashing functions in SQL Server and Oracle yield different results when hashing the non-breaking space character?
Oracle select standard_hash('a ', 'MD5') from dual; results in 25EF28EB5A5BE667C6222418E9E27E8E and doesn't match SQL select HASHBYTES ('MD5','a '); results in CE8F03020C81133B3A082F8051EB9FF6. Note the space after the input 'a' is a non-breaking space character.
Is there any good source that can lay out the differences?
This appears to be a character set or "collation" issue, where Oracle is in UTF-8 and SQL Server is in Latin 1252. My solution was to CONVERT the value to Windows Latin-1252 in Oracle before calculating the hash: select STANDARD_HASH(CONVERT('a ','WE8MSWIN1252'), 'MD5') from dual.
To find my collation/character set I did SELECT collation_name FROM sys.databases WHERE name = 'MY_DB_NAME'; in SQL Server and select * from nls_database_parameters where parameter='NLS_CHARACTERSET'; in Oracle.
First of all you need to establish which one is actually yielding "different" results:
Using your favourite search engine to find online hash generators and testing results.
External Resources
https://passwordsgenerator.net/md5-hash-generator/ - 99020CB24BD13238D907C65CC2B57C03
https://www.md5hashgenerator.com/ - 99020cb24bd13238d907c65cc2b57c03
https://www.miraclesalad.com/webtools/md5.php - 99020cb24bd13238d907c65cc2b57c03
SQL Server
select HASHBYTES ('MD5', 'a ')
SQL Server 2014 SP3 (12.0.6024.0) - 0x99020CB24BD13238D907C65CC2B57C03
SQL Server 2019 (15.0.2080.9) - 0x99020CB24BD13238D907C65CC2B57C03
Oracle (using https://dbfiddle.uk/)
select standard_hash('a ', 'MD5') from dual;
Oracle 21c - 0x99020CB24BD13238D907C65CC2B57C03
Oracle 18c - 0x99020CB24BD13238D907C65CC2B57C03
Oracle 11gR2 - "ORA-00904: "STANDARD_HASH": invalid identifier"
Conclusion
You can see that your Oracle produced answer differs even from other Oracle answers. What version of Oracle are you running? What other options are set, such as collation etc.?

FireDAC Query dropping special characters in SQL statement to SQL Server

I have hit this issue off and on in Delphi 10.3 using FireDAC and the EMS Rad Server. I have not experienced it in Delphi 10.2 or below, but I am not using FireDAC anywhere but in Delphi 10.3.
The issue I am experiencing is some special characters seem to be getting stripped out of the SQL statements before they reach the Database.
For example, if I run:
update messageread set
MessageDeliveredDateTime = '8/11/2020 6:33:45 PM'
where messageread.dts in ('5/7/2020 12:48:20 PM-!+[[786', '5/7/2020 12:47:06 PM-!#[[782', '5/7/2020 12:43:35 PM-&K[[775', '5/7/2020 12:41:01 PM-&K[[773')
what gets executed on the SQL server is:
update messageread set MessageDeliveredDateTime = '8/11/2020 6:33:45 PM' where messageread.dts in ('5/7/2020 12:48:20 PM-+[[786', '5/7/2020 12:47:06 PM-[[782', '5/7/2020 12:43:35 PM-[[775', '5/7/2020 12:41:01 PM-[[773')
It appears to be dropping 2 characters after the "-". Because it is 2 characters, it makes me thing its some Unicode thing.
In the past, I have worked around this by using parameterized queries, but in this case, it still isn't helping. The Delphi code that I am currently running is:
fdTemp.SQL.Text := 'update messageread set MessageDeliveredDateTime = ' + QuotedStr(DateTimeToStr(now)) + ' where messageread.dts in (' + sUpdateDTS + ')';
fdTemp.ExecSQL;
sUpdateDTS = '5/7/2020 12:48:20 PM-!+[[786', '5/7/2020 12:47:06 PM-!#[[782', '5/7/2020 12:43:35 PM-&K[[775', '5/7/2020 12:41:01 PM-&K[[773'
Where fdTemp is TFDQuery and DTS is the primary key of the table.
If I take the SQL statement and run it in Mgt Studio, it works just fine. However when run from Delphi, 0 rows are affected because nothing matches the where clause.
Does anyone have any idea?
Some characters in SQL commands have special meaning in FireDAC and thus have to be entered in a special way. In your case an identifier starting with & is treated as a macro.
You can suppress that by setting ResourceOptions.MacroCreate to false.
More info on special character handling in FireDAC can be found in the documentation:
Special Character Processing

Insert on linked table (from MS Access to SQL Server) fails because of field length

I'm trying to do an append query from MS Access into SQL server. The SQL server column is varchar(max) which I thought meant it can accept more than 4000 characters
I get the following error when running this query from VBA in MS Access
Run Time Error 3155 ODBC - insert on a linked table
failed [Microsoft] [SQL Server Native Client 10.0] {SQL Server] The
size (7596) given to the parameter '#P6' exceeds the maximum allowed
(4000). (#2717)
adding my queries
this query is based on an linked outlook folder, Deleted Items
SELECT Trim(Mid([contents],InStr([contents],"Short Description: ")+19,(InStr([contents],"Requestor: ")-1)-(InStr([contents],"Short Description: ")+19)-3)) AS ShortDesc, Trim(Mid([contents],InStr([contents],"Requestor: ")+10,(InStr([contents],"Requestor EMail: ")-1)-(InStr([contents],"Requestor: ")+10)-3)) AS Requester, Trim(Mid(Mid([contents],InStr([contents],"Office Location: ")+3),InStr(Mid([contents],InStr([contents],"Office Location: ")),"Description:")+13,(InStr(Mid([contents],InStr([contents],"Office Location: ")),"Assigned Task: ")-1)-(InStr(Mid([contents],InStr([contents],"Office Location: ")),"Description:")+13)-3)) AS Description, Trim(Mid([contents],InStr([contents],"Request Item: ")+14,12)) AS TicketNoText, Val(Mid([contents],InStr([contents],"Request Item: ")+19,7)) AS TicketNo, Val(Mid([contents],InStr([contents],"Assigned Task: ")+19,7)) AS TaskNo, Mid([contents],InStr([contents],"Delivery Date: ")+15,10) AS DeliveryDate, Trim(Mid([contents],InStr([contents],"Requestor EMail: ")+17,(InStr([contents],"Office Location: ")-1)-(InStr([contents],"Requestor EMail: ")+17)-3)) AS RequesterEMail
FROM [Deleted Items]
WHERE ((([Deleted Items].From)="xxxxxxx#service-now.com") AND (([Deleted Items].Subject)="you just assigned a ticket to yourself"));
then, the append query is based on this one and a few other ones
INSERT INTO PROJECTS ( TaskNo, RequesterID, Description, TicketNo, ProjectFolderLink, SNLink, OpenedOn, DateDue )
SELECT QSNNew.taskno, cmbRequesters.RequesterID, "SHORT DESCRIPTION: " & [shortdesc] & Chr(13) & Chr(10) & Chr(13) & Chr(10) & "DESCRIPTION: " & [Description] AS Expr4, QSNNew.TicketNo, "#\\link to a network folder" & lpad([ticketno],"0",7) & "\#" AS Expr1, "#https://xxxx.service-now.com/nav_to.do?uri=sc_task.do?sysparm_query=number=TASK" & lpad([taskno],"0",7) & "#" AS Expr2, Now() AS Expr3, Mid([DeliveryDate],6,2) & "/" & Right([DeliveryDate],2) & "/" & Left([DeliveryDate],4) AS Expr5
FROM (QSNNew LEFT JOIN PROJECTS ON QSNNew.TicketNo = PROJECTS.TicketNo) LEFT JOIN cmbRequesters ON QSNNew.[Requester] = cmbRequesters.RequesterName
WHERE (((PROJECTS.TicketNo) Is Null));
in case anyone is wondering what I'm doing, I'm loading tickets from Service Now into an Access database and there's no other way of doing it, other than parsing notification emails i get from Service Now when a ticket is assigned to me.
So I'm parsing those emails and creating my own version with links to the ServiceNow page, network folders for the ticket, etc.
It's a matter of driver (SQL Native Client and ODBC Driver 17 are limited to 4000 chars). If you use SQL Server Driver (10.09.18362.01) limit is 64000 chars.
As yu2 suggested ADODB query would avoid that (ODBC Passthrough should do it too).
The parameter #P6 is produced by ODBC see Optimizing Microsoft Office Access Applications Linked to SQL Server Understanding Dynasets
This is answer for your question
3155 Insert into Linked Table error
On this link Microsoft recommends to use ADODB instead of ODBC if you can't decrease field size in application.
ODBC protocol is generally for big data -- sql server -- which uses "Fire Hose" bandwith. Access uses (my term) garden hose bandwith (with all due respect for mini RDBMSs) because Access is basically a mini RDBMS (relational database management system) which is also file based. Unless everything (front/back ends) is set up perfectly and conditions are ideal -- you will encounter the problem you are having. Microsoft came up with ADODB as a workaround for this problem. When I have to interface between sql server and Access -- I use ADODB. This has proven to be much more reliable and consistent between the small and large RDBMSs. Here is some sample ADODB code for reading from and writing to a Sql Server from Access
'--add a reference in Tools/References to Microsoft ActiveX Data Objects 2.x Library '--(2.5 or higher)
...
The Access "Long Text" column can contain a text string up to a gigabyte in size. The message says you are trying to fit 7596 characters into a 4000 character field.
If so, your SQL server database should be exposing an ODBC LongVarChar column instead of VarChar.
LongVarChar is an ODBC type. The mapping is done by the ODBC driver. If you use an ODBC driver that maps VarChar(MAX) to a VarChar ODBC column, you can either get a different driver, or, possibly, use a SQL SERVER 'TEXT' column instead. TEXT is the old SQL Server column type, from when VarChar could only go to 4000. Old ODBC drivers recognize that TEXT columns map to LongVarChar.
I think the error message is quite helpful.
You are trying to fit a string with length of 7596 while your maximum varchar length is 4000.
I guess you either truncate it or store it as a blob.

OPENROWSET or OPENDATASOURCE Example to get Data from .xlsx or .csv file on file system of Remote Server

There are plenty of examples around showing how to use OPENROWSET and OPENDATASOURCE to open queries against tables on remote SQL servers, and to get data from files on other servers. Unfortunately, none of them tell me how to do the specific thing that I need to do, which is use one of these commands to get either a .csv or .xlsx Excel file from a remote server using the server IP address and windows login where the server has no SQL Server instance installed - only either IIS7 or 8.
It would be great if Microsoft documentation didn't omit basic examples of how to use their tools in the most likely of ways. It takes no real intelligence to try 40 odd different combinations of parameters list: it's just an inefficient waste of time. Developers have more important things to do than waste hours trying to discover some 'secret knowledge' recipe which is really just a not-properly-documented variant of the command parameters, and pretending that this is something to do with being clever.
So to assuage my philosophical angst, could someone please provide an example of how to use either OPENROWSET or OPENDATASOURCE to get/select content from either a .csv file or an excel spreadsheet using the remote server IP address XXX.XXX.XXX.XXX, a port number if it should be included, the file system path correctly appended to that or included in the command, and the correct arrangement of the username and password parameters. There is no SQL server instance on the remote server - just IIS and a website with windows auth. If you have an example that works with SQL server instance on the remote server, that will do (although I think some of the REMOTEDATASOURCE examples cover this already) but I REALLY want an example where I don't have to have an SQL server instance on the remote web server.
I know that you can use linked servers for this, but there is some extra baggage to put on the remote server containing the file to access, and in my case the server containing the excel or .csv text file will not even have a SQL Server instance on it - only IIS and a website.
(Also - can someone confirm whether you can use linked servers with NO SQL Server or other database server instance on the remote server with the desired text data file? Is it linked database servers only, or linked servers where the remote server can just be a windows and web server with no SQL server installed on it?)
This example is handy, but does not tell me if SERVERPROPERTY('MachineName') AS nvarchar(128))
can contain an IP address of a remote windows server with no SQL server instance on it, and it is not about accessing text files.
This example comes blisteringly close, but there does not seem to be a positive outcome in the post, and there is no text file involved - only a DB query so the remote system has SQL server installed?:
SELECT *
FROM OPENROWSET('PACISOleDb', '192.168.200.172';'admin';'admin', 'SELECT * FROM DB')
Existing examples that are good but don't help much:
SELECT *
FROM OPENROWSET('SQLNCLI',
'DRIVER={SQL Server};SERVER=YourServer;UID=UserID;PWD=Password',
'select * from sys.sysobjects')
(Source)
SELECT ContactName, CompanyName, ContactTitle
FROM OPENDATASOURCE('SQLOLEDB',
'Data Source=ServerName;User ID=MyUID;Password=MyPass' ).Northwind.dbo.Customers
(source)
-- SQL Server 2012
SELECT
*
FROM
OPENDATASOURCE ('SQLNCLI11',
'Data Source=SQLInstanceName;Catalog=DBName;User ID=SQLLogin;Password=Password;').DBName.SchemaName.TableName
SELECT *
FROM OPENROWSET('SQLNCLI11',
'DRIVER={SQL Server};SERVER=SQLInstanceName;UID=SQLLogin;PWD=Password',
'select * from DBName..TableName')
--Access DB
SELECT * FROM OPENDATASOURCE ('Microsoft.ACE.OLEDB.12.0',
'Data Source=D:\MyDB\MyAccessDB.accdb')...TableName
(source)
SELECT *
FROM OPENROWSET('SQLNCLI',
'DRIVER={SQL Server};SERVER=MyServer;UID=MyUserID;PWD=MyCleverPassword',
'select ##ServerName')
(source. I take it that {SQL Server} here has to be a SQL server name - not a remote IP Address? It is not clear.)
SELECT *
FROM OPENROWSET('Microsoft.Jet.OLEDB.4.0',
'Excel 8.0;Database=C:\test.xls;HDR=No',
'SELECT * FROM [Sheet1$]') b
(source)
--Excel 2007-2010
SELECT * --INTO #productlist
FROM OPENROWSET('Microsoft.ACE.OLEDB.12.0',
'Excel 12.0 Xml;HDR=YES;Database=C:\temp\Products.xlsx',
'SELECT * FROM [ProductList$]');
--Excel 97-2003
SELECT * --INTO #productlist
FROM OPENROWSET('Microsoft.Jet.OLEDB.4.0',
'Excel 8.0;HDR=YES;Database=C:\temp\Products.xls',
'select * from [ProductList$]');
(source. Again - no remote server, no IP server address, no credentials)
Lots to chose from here. GREAT blog post, but not useful for my specific ends:
SELECT *
FROM OPENROWSET('Microsoft.ACE.OLEDB.12.0',
'Excel 12.0 Xml;
Database=C:\DataFiles\EmployeeData1.xlsx',
[vEmployee$]);
SELECT *
FROM OPENDATASOURCE('Microsoft.ACE.OLEDB.12.0',
'Data Source=C:\DataFiles\EmployeeData1.xlsx;
Extended Properties=Excel 12.0 Xml')...[vEmployee$];
SELECT *
FROM OPENROWSET('Microsoft.ACE.OLEDB.12.0',
'Excel 12.0 Xml; HDR=YES;
Database=C:\DataFiles\EmployeeData1.xlsx',
[vEmployee$]);
SELECT *
FROM OPENROWSET('Microsoft.ACE.OLEDB.12.0',
'Excel 12.0 Xml; HDR=NO;
Database=C:\DataFiles\EmployeeData1.xlsx',
[vEmployee$]);
SELECT * INTO EmployeeInfo3
FROM OPENROWSET('Microsoft.ACE.OLEDB.12.0',
'Excel 12.0 Xml; HDR=YES; IMEX=1;
Database=C:\DataFiles\EmployeeData1.xlsx',
[vEmployee$]);
(source)
The MS openrowset documentation has an '|' in the command schema suggesting this cannot be done remotely:
SELECT *
FROM OPENROWSET(BULK N'D:\XChange\test-csv.csv',
FORMATFILE = N'D:\XChange\test-csv.fmt',
FIRSTROW=2,
FORMAT='CSV') AS cars;
H. Accessing data from a CSV file without a format file:
tsql
Copy
SELECT * FROM OPENROWSET(
BULK 'C:\Program Files\Microsoft SQL Server\MSSQL14.CTP1_1\MSSQL\DATA\inv-2017-01-19.csv',
SINGLE_CLOB) AS DATA;
So I am thinking that the correct OR ONLY approach involves OPENDATASOURCE with the jet driver present and accessible on the remote server. However, where in the following example from MS does the IP address of the remote server and the login password and username go? If it cannot then that seems contradictory to the claims of the capability of the command in the documentation (based on the words they use), and it would be great if they could say 'you cannot do this', as it is pretty clear that most people will try...
SELECT * FROM OPENDATASOURCE('Microsoft.Jet.OLEDB.4.0',
'Data Source=C:\DataFolder\Documents\TestExcel.xls;Extended Properties=EXCEL 5.0')...[Sheet1$] ;
So,
Something like:
SELECT * FROM OPENDATASOURCE('Microsoft.ACE.OLEDB.12.0'|'Microsoft.Jet.OLEDB.4.0'|'PACISOleDb', 'Data Source=XXX.XXX.XXX.XXX\DataFolder\Documents\TestExcel.xls';User ID=MyUID;Password=MyPass;Extended Properties=EXCEL 5.0')...[Sheet1$] ;
or maybe
(TWIDDLING THUMBS - BORING BORING BORING)
I should give up and use a linked server:
EXEC sp_addlinkedserver
#server = 'ExcelLinkSrv1',
#srvproduct = 'Excel',
#provider = 'Microsoft.ACE.OLEDB.12.0',
#datasrc = 'C:\DataFiles\EmployeeData1.xlsx',
#provstr = 'Excel 12.0 Xml; HDR=YES; IMEX=1';
GO
But again - can I have:
#server = '202.217.XXX.XXX'
?
Yes - I know that you would normally not hard code it, but let's start simple in SSMS. I wanted to avoid linked server for different reasons. How do you do it with OPENROWSET or else OPENDATASOURCE against excel spreadsheet or else .csv file?
You can have all of my reputation points or whatever they are if your solution or information works (and someone else did not get them first), because I don't care about that stuff.
Simply use windows sharepaths for that.
EXEC sp_addlinkedserver
#server = 'ExcelLinkSrv1',
#srvproduct = 'Excel',
#provider = 'Microsoft.ACE.OLEDB.12.0',
#datasrc = '\\SERVEROTHER\c$\DataFiles\EmployeeData1.xlsx',
#provstr = 'Excel 12.0 Xml; HDR=YES; IMEX=1';
An Excel connection string has specific requirements, which are based on connection DLL string mappings based on the provider you have selected (ACE/JET). This then is translated to behavior defined in the registry, which is difficult to parse.
The underlying technology used to interact with your provided string is OLE Data Access which is of course COM based.
As others pointed out, you may use a sharepath, but I wanted to provide more detail.
Information about the internals of these providers is difficult to come by, and official MSFT documentation on the matter is no longer directly accessible online (I would imagine there is an archive somewhere on Excel Data Sources in one giant PDF, but I was unable to locate it). COM-based reading material is generally all been deprecated or removed, despite its integral role in the Windows OS.
I share your sentiment about these commands. If it helps at all, here are the details of the "secret" commands within OPENDATASOURCE, taken from https://www.codeproject.com/Articles/37055/Working-with-MS-Excel-xls-xlsx-Using-MDAC-and-Oled (at risk of being lost as well):
The connectionstring has some parts:
Provider: It is the main oledb provider that is used to open the Excel
sheet. This will be Microsoft.Jet.OLEDB.4.0 for Excel 97 onwards Excel
file format and Microsoft.ACE.OLEDB.12.0 for Excel 2007 or higher
Excel file format (One with xlsx extension)
Data Source: It is the entire path of the Excel workbook. You need to mention a dospath that corresponds to an Excel file. Thus, it will
look like: Data Source=C:\testApp.xls".
Extended Properties (Optional): Extended properties can be applied to Excel workbooks which may change the overall activity of the Excel
workbook from your program. The most common ones are the following:
HDR: It represents Header of the fields in the Excel table. Default is YES. If you don't have fieldnames in the header of your
worksheet, you can specify HDR=NO which will take the columns of the
tables that it finds as f1,f2 etc.
ReadOnly: You can also open Excel workbook in readonly mode by specifying ReadOnly=true; By default, Readonly attribute is false, so
you can modify data within your workbook.
FirstRowHasNames: It is the same as HDR, it is always set to 1 ( which means true) you can specify it as false if you don't have your
header row. If HDR is YES, provider disregards this property. You can
change the default behaviour of your environment by changing the
Registry Value
[HKLM\Software\Microsoft\Jet\4.0\Engines\Excel\FirstRowHasNames] to 00
(which is false)
MaxScanRows: Excel does not provide the detailed schema defination of the tables it finds. It need to scan the rows before
deciding the data types of the fields. MaxScanRows specifies the
number of cells to be scanned before deciding the data type of the
column. By default, the value of this is 8. You can specify any value
from 1 - 16 for 1 to 16 rows. You can also make the value to 0 so that
it searches all existing rows before deciding the data type. You can
change the default behaviour of this property by changing the value of
[HKLM\Software\Microsoft\Jet\4.0\Engines\Excel\TypeGuessRows] which is
8 by default. Currently, MaxScanRows is ignored, so you need only to
depend on TypeGuessRows Registry value. Hope Microsoft fixes this
issue to its later versions.
IMEX: (A Caution) As mentioned above, Excel will have to guess a number or rows to select the most appropriate data type of the
column, a serious problem may occur if you have mixed data in one
column. Say you have data of both integer and text on a single column,
in that case, Excel will choose its data type based on majority of the
data. Thus it selects the data for the majority data type that is
selected, and returns NULL for the minority data type. If the two
types are equally mixed in the column, the provider chooses numeric
over text.
For example, in your eight (8) scanned rows, if the column contains five (5) numeric values and three (3) text values, the
provider returns five (5) numbers and three (3) null values.
To work around this problem for data, set "IMEX=1" in the Extended Properties section of the connection string. This enforces
the ImportMixedTypes=Text registry setting. You can change the
enforcement of type by changing
[HKLM\Software\Microsoft\Jet\4.0\Engines\Excel\ImportMixedTypes] to
numeric as well.
Thus if you look into the simple connectionstring with all of them, it will look like:
Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\\testexcel.xls;
Extended Properties=\"Excel 8.0;HDR=YES;IMEX=1;MAXSCANROWS=15;READONLY=FALSE\""
or:
Copy Code
Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\\testexcel.xlsx;
Extended Properties=\"Excel 12.0;HDR=YES;IMEX=1;MAXSCANROWS=15;READONLY=FALSE\""
We need to place extended properties into Quotes(") as there are multiple number of values.
If you want to link to csv files, Erland Sommarskog has a very good article: here, which discusses the practical use of OPENROWSET (BULK) , as well as BCP and BULK IMPORT . As he points out in detail, there are number of gotchas, especially if you are stuck with a version of SQL Server before 2017.
The layout of the csv file may not allow you to use OPENROWSET (BULK) without some prior processing. The article gives full details. If it is possible, however, it is by far the fastest method for gulping large volumes of text into a SQL Server database.
Here is a simple SQL query for CSV import using opendatasource and the access text driver 64 bit
SELECT * FROM OPENDATASOURCE('Microsoft.ACE.OLEDB.12.0',
'Text;Database=D:\TEMP;HDR=YES')..[pdf_attachment#csv]

Calling a SQL Server stored procedure from Visual Foxpro 9

I have been trying to call a SQL Server stored procedure that has no parameters and no return values. All it does is recalculate data in a SQL Server database.
I thought I could use something simple like
lsqlcmd = " execute storedprocname"
but the procedure is not being called and I am not receiving an errors.
Any suggestions?
Can you try calling it in SQLEXEC()? This how I've seen it done:
TEXT TO lcSQLCommand
<database>.<schema>.<sproc>
ENDTEXT
gcConnectionString = [Driver={SQL Server Native Client 10.0};Server=] + "<servername>" + [;Database=] + "<database>" + [;Trusted_Connection=yes]
STORE SQLSTRINGCONNECT(gcConnectionString) TO gnConnHandle
SQLEXEC(gnConnHandle, lcSQLCommand)
You'll need to update the connection string to however your database is configured, this was for windows authentication.

Resources