I'm using ADODB connections to connect to a database which none of my other colleagues understand how to connect to. So far I've got as far as being able to see all the available tables via 2 methods:
Dim ado as object
set ado = CreateObject("ADODB.Connection")
Call ado.open("...")
set rs = ado.Execute("SELECT * FROM sys.objects WHERE type='U'")
and also
const adTable = 20
Set rstSchema = ado.OpenSchema(adTable)
Do Until rstSchema.EOF
Debug.Print rstSchema("TABLE_NAME")
rstSchema.MoveNext
Loop
But the part which is confusing me is selecting from the tables directly... I expected to be able to do:
select * from <<TABLENAME>>
where <<TABLENAME>> was one of the table names returned by the above 2 methods. However whenever I do this I get the error in the title:
Invalid object name '<<TABLENAME>>'.
So how exactly am I meant to access the data in the tables identified from OpenSchema() method. Is there another method which I am unfamiliar with?
As discussed with itsLex in the comments:
In SQL Server terms:
select * from <<Database>>.<<Owner>>.<<TableName>>
Alternatively you can use the USE statement as follows:
USE <<Database>>;
select * from <<TableName>>;
Related
I have a form that is linked to an ODBC (MS SQLServer), that is displaying a result of a VIEW, when I try to delete a record, I'm invoking a function at VBA level
Form_BeforeDelConfirm(Cancel As Integer, Response As Integer){
If (IsNull(Text104.value) = False) Then
Dim deleteLabel As DAO.QueryDef
Set deleteLabel = CurrentDb.CreateQueryDef("")
deleteLabel.Connect = CurrentDb.TableDefs("KontrollWerte").Connect
If (InStr(QuerySave, "KontrollWerteVIEW") <> 0) Then
deleteLabel.sql = "delete from KontrollWerte_Label where Kontrolle_Label_ID = " & Text104.value
End If
Close
End If
}
Error shown:
[Microsoft][SQL Server Native Client 11.0][SQL Server] View or function 'dbo.KontrollwerteVIEW' is not updatable because the modification affects multiple base tables. (#4450)
This error is okay, as the view is a select with multiple tables.
It seems the function is not called at all, and the "default" delete function of the MS Access is being called, there is a way to say to MS Access don't do the default delete and instead execute my sql statement inside of the Form_BeforeDelConfirm function?
Thanks!
I tried to change when the call of function is called, but no luck.
You have to ensure that the view allows updates.
When you link a table, and it is a view?
The during the creating of the table link, then you will see this prompt:
First, we select the "view" when linking that "view/table"
and note I also checked the Save password option.
Then next we get/see this:
DO NOT skip the above prompt. If you don't select the PK column for that view, then it will be read only.
FYI:
The above prompt to save password, and the above prompt to select the PK when linking to that view?
It DOES NOT appear on re-link, ONLY when adding a new link!!!!
So, that's why I stated to delete the link to sql server (not just re-link and not just re-fresh table link, but Adding for first time are the key instructions here).
So, yes, views are and can be up-datable, but you MUST answer the above prompt during the linking process in Access, or the result is a read-only table.
I work with large databases that needs to be stored into a server.
So, to work with them on Rstudio I have to open a connection to my Microsoft SQL Server with the dbConnect function :
conn <- dbConnect(odbc(),"myconnection",uid="***",pwd="***",schema="dbo",access="readonly")
and in order to use dplyr, I have to create data references with the tbl function :
data <- tbl(conn, "data")
But one of the online dataframe contains a columns that I can't read because I dont have the access, but I can read everything else.
The SQL query behind the tbl() function is :
SELECT * FROM data
and this is my problem.
Even when I try to select a specific column it doesn't work (see below), so I can't create my references and I can't work.
select(tbl(conn, "data"), "columnX")
=
SELECT columnX FROM data
I think this is the tbl() function and the call of "SELECT *" that blocks me.
Do you know what can I do ? Is there smilar functions that could resolve my problem ?
If you know the columns that you have access to, then one option is to bypass the default access SELECT * FROM ... with your own SQL query.
A remote table is defined by two components:
The database conneciton
The query to the database
When you connect with the default approach tbl(conn, 'data') then it defaults to a query SELECT * FROM data.
But here is another approach:
custom_query = 'SELECT columnX FROM data'
remote_table = tbl(conn, dbplyr::sql(customer_query))
Using Delphi 10.3.3, mainly under Windows10, I have a number of [FireDAC] TFDTable components accessing an SQL Server DB.
Everything worked fine in delphi 10.2.3 but in the Rio version, I find that those TFDtables which have an indexname set and which access a DB whose name has a space in it, fail with the message "[FireDAC]{DatS]-2 Object [PK_DEPT] is not found."
An example of the table definition in the dfm is:
object tbHODEPT: TFDTable
IndexName = 'PK_DEPT'
ConnectionName = 'HEADOFFICE'
FetchOptions.AssignedValues = [evMode]
FetchOptions.Mode = fmAll
UpdateOptions.UpdateTableName = 'DEPT'
TableName = 'DEPT'
The connection, "HEADOFFICE", is a TFDConnection descendant which just adds the credentials for the relevant DB at open-time. I have noticed that if I supply a fully qualified TableName property (e.g. '[Some DBname].dbo.[DEPT') then the problem does not occur. But setting the DBname at design time is undesirable as we allow the DB names to be configurable.
Barring a solution, my options seem to be
Renaming the problematic DB, and
Changing all of the affected TFDTables to use indexfieldnames instead. (This works OK).
Ideas welcome.
In sqlserver I have a function which generates a complex xml of all products with several tables joined: location, suppliers, orders etc.
No problem in that, it runs in 68 sec and produces around 450MB.
It should only be called occationally during migration to another server, so it doesn't matter it takes some time.
I want to make this available for download over webserver.
I've tried some variations of this in classic asp:
Response.Buffer = false
set rs=conn.execute("select cast(dbo.exportXML() as varchar(max)) as res")
response.write rs("res")
But I just get a standard
An error occurred on the server when processing the URL. Please contact the system administrator.
If you are the system administrator please click here to find out more about this error.
Not my usual custom 500-errorhandler, so I'm not sure how to find the error.
The problem is in response.write rs("res"), if i just do
temp = rs("res")
the script runs, but displays nothing of cause; if I then
response.write temp
I get the same failure.
So the problem is writing such a ling string.
Can I save the file from tsql directly; and run the job periodically from sql agent?
I found that there seems to be a limit on how much data can be written at once using Response.Write. The workaround I used was to break the data into chunks like this:
Dim Data, Done
Done = False
Do While Not Done
Data = RecordSet(0).GetChunk(8192)
If Not Len(Data) = 0 Then
Response.Write Data
Else
Done = True
End If
Loop
Try this:
Response.ContentType = "text/xml"
rs.CursorLocation = 3
rs.Open "select cast(dbo.exportXML() as varchar(max)) as res",conn
'Persist the Recordset in XML format to the ASP Response object.
'The constant value for adPersistXML is 1.
rs.Save Response, 1
We are in the process to migrate our SQL 2000 box to SQL 2008. But we ran into an issue; when a result set (rows or not) is returned by using a query that has a UNION. Later in the code we try to add a new row and assign field to it but because a UNION was used, when we try to assign a value to the field it gives us a Multiple-step operation generated errors. Check each status value. error. We tried the following code on a Windows XP & Windows 7 and got the same result. But when we change our connection string to point back to our SQL 2000 box we don't get that error any more.
The following example show the problem we are having.
var c = new ADODB.Connection();
var cmd = new ADODB.Command();
var rs = new ADODB.Recordset();
object recordsAffected;
c.Open("Provider=SQLOLEDB;Server=*****;Database=*****;User Id=*****;Password=*****;");
cmd.ActiveConnection = c;
cmd.CommandType = ADODB.CommandTypeEnum.adCmdText;
cmd.CommandText = "create table testing2008 (id int)";
cmd.Execute(out recordsAffected);
try {
cmd.CommandText = "select * from testing2008 union select * from testing2008";
rs.CursorLocation = ADODB.CursorLocationEnum.adUseClient;
rs.Open(cmd, Type.Missing, ADODB.CursorTypeEnum.adOpenDynamic, ADODB.LockTypeEnum.adLockBatchOptimistic, -1);
rs.AddNew();
rs.Fields["id"].Value = 0; //throws exception
rs.Save();
}
catch (Exception ex) {
MessageBox.Show(ex.ToString());
}
finally {
cmd.CommandText = "drop table testing2008";
cmd.Execute(out recordsAffected);
c.Close();
}
The link below is an article that gives a great breakdown of the 6 scenarios this error message can occur:
Scenario 1 - Error occurs when trying to insert data into a database
Scenario 2 - Error occurs when trying to open an ADO connection
Scenario 3 - Error occurs inserting data into Access, where a fieldname has a space
Scenario 4 - Error occurs inserting data into Access, when using adLockBatchOptimistic
Scenario 5 - Error occurs inserting data into Access, when using Jet.OLEDB.3.51 or ODBC driver (not Jet.OLEDB.4.0)
Scenario 6 - Error occurs when using a Command object and Parameters
http://www.adopenstatic.com/faq/80040e21.asp
Hope it may help others that may be facing the same issue.
It is type mismatch, try
rs.Fields["id"].Value = "0";
or make sure you assign a Variant to the value.
Since I posted this problem, we figured out that the problem was when you do a union the attributes on the fields are not bound (i.e. the attributes: basecatalog, basetable & basecolumn are empty) to remedy our problem we had to force the values of those attributes, by saving the recordset to xml (adPersistXML), change the xml and reopen the recordset from the xml. This rebound the fields and we were able to continue. We know this may not be the most efficient solution, but it was for an older app and we didn't want to rewrite the sql statements. It looks like the main error Multiple-step operation generated errors. Check each status value. is related to when an error occurs when a value is assigned to a field.
Two things I can think of... Make sure your "ID" column will accept a zero (0). Also - I've stopped this issue on one occasion by not using the adUseClient cursor (try server).
Many times this is a type mismatch, trying to stuff a NULL into a non-null column, or attempting to write more characters into a column than it's designed to take.
Hope this helps. - Freddo
Same issue occurred to me the problem was that i violated an object property , in my case it was size the error came out as
"IntegrationException: Problem (Multiple-step operation generated errors. Check each status value.)"
Imports ADODB
Dim _RecordSet As Recordset
_rs.Fields.Append("Field_Name", DataTypeEnum.adVarChar, 50)
_Recordset("Field_Name").Value = _RecordDetails.Field_NameValue
_RecordDetails.Field_NameValue length was more than 50 chars , so this property was violated , hence the error occurred .
I found another scenario:
When I was trying to set the value of a adLongVarChar field in a new record for a memory-only adodb.recordset. In my case, the error was triggered because the string I was passing had a buried unicode character.
I found this error when our legacy application was trying to parse 1/1/0001 12AM date and time. Looks like VB6 recordsets doesn't like that value.
To get rid of the errors, I had to set all the offending dates to null.
I was getting this error when trying to insert/update the field with a value that did not match the table>field type.
For example, the database table > field was
char(1)
however, I was trying to insert/update
"apple"
into the record.
Once I change the inputted value to "a" and it worked.