0

I have an access database for which I need to run a query that is available in postgres DBs, I was wondering if there is a possible that this can be accomplished:

Insert into Table (Col1,Col2...) values(Val1,Val2,...) returning * (ore even just an id defining that specific set of data that was just inserted)? 

I'm using c# to communicate to the DB.Anything would help, thank you.

The code I basically use is the following :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.OleDb;

namespace Testquery1
{
    class Program
    {

        static void Main(string[] args)
        {

            string query = "INSERT INTO Table ( Val1, Val2, Val3 ) values(14,2,1)";
            Test1 queryselect = new Test1();
            queryselect.dataconnection(query);
        }


    }
    class Test1
    {

        public OleDbConnection connection = new OleDbConnection();
        string path = System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
        string fileloc = @"DataBase.accdb";
        string provider = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=";
        public void dataconnection(string query)
        {

            connection.ConnectionString = provider + path + fileloc;
            Console.WriteLine(connection.ConnectionString);
            connection.Open();
            OleDbCommand command = new OleDbCommand();
            command.Connection = connection;
            command.CommandText = query;
            command.ExecuteNonQuery();
            connection.Close();
        }
    }
}
VericalId
  • 105
  • 12
  • I mean I call the database from a c# app. I have used raw sql to make the calls – VericalId Mar 08 '19 at 21:42
  • The code I basically use to call my database is basically what I have above. And I use access database – VericalId Mar 08 '19 at 22:55
  • An the thing I tried the Pass-Though Query as suggested in the UI that access 2016 has for inputing sql and it does not work – VericalId Mar 08 '19 at 22:56
  • You want to execute a query like the Postgre-Query, but in`MS Access`and you want to write into the access db table not into postgre db? – ComputerVersteher Mar 08 '19 at 23:02
  • Correct, I know that in postgres you can insert series of data into a table the call the returning method to get in this case the id of that row that was just written. I have searched around on how to get the last id written I have found several solutions one that worked and had been using was to use the method Last() as follows: "Select Last(id) from Table"; but I run into a weird issue that sometimes the id of 2 transactions ago is being used instead of the one that I want. – VericalId Mar 08 '19 at 23:09
  • 1
    Then`SELECT @@IDENTITY` ([Autonumber of last insert](https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/retrieving-identity-or-autonumber-values#retrieving-microsoft-access-autonumber-values)) is what you are looking for? – ComputerVersteher Mar 08 '19 at 23:14
  • Possible duplicate of [Autonumber value of last inserted row - MS Access / VBA](https://stackoverflow.com/questions/1628267/autonumber-value-of-last-inserted-row-ms-access-vba) – Andre Mar 08 '19 at 23:16
  • @Andre, no dupe (but very similar), because it refers to C#`OleDB`, not VBA `DAO`. – ComputerVersteher Mar 08 '19 at 23:17
  • Let me give it a shot Ill post here my findings.Thanks – VericalId Mar 08 '19 at 23:38
  • Yes Select Last() is the Last thing I wanna use, I was starting to think to change databases, I don't know one database that would work sort of out of the box as access does. I mean yes postgres does but I might have to make a make file or something to run at installation as well as install postgres itself automatically at installation of my app which I do not how to do that yet. – VericalId Mar 09 '19 at 00:11
  • @atds9511, As I wrote, the select works reliable, if you do it before the insert, then insert the adapted result (+1 for max()) explicit. If your database is only for local use of the app, I would recommend`Sqlite`. – ComputerVersteher Mar 09 '19 at 01:13
  • @atds9511, please improve your question! Add the important infos from the comments. like you are "looking for the last id written" (then delete them). Change the tags on question (First should be`C#`, also add the `ms-jet-ace`tag, what is for databases not used with`MS Office`). Clearify the title (Shame on you for wasting @Alberts time), as it suggest a connection between Postgre/Access, not the version of the Postgre Command`Returning *`. if`SELECT @@IDENTITY`is what you needed. please post the code as an answer. – ComputerVersteher Mar 09 '19 at 04:10

1 Answers1

0

Unfortunately with .net you cannot do a append or make table query between two different connections.

However, you CAN in Access.

If you have a working PostgreSQL SQL query that returns records, then you can simple save that query in Access (as a pass-through query.

You can now use that query in Access and send it to a NEW local table in Access. (Access supports this concept, .net does not)

You can thus either append or “make table” of that data.

And more interesting is you can even append between different connections in Access. So you can append from a PostgreSQL table to say a MySQL, or Oracle or FoxPro table inside of access.

Again, you can’t do this in .net.

So, assume a working raw SQL (PostgreSQL format) query that works in PostgreSQL? Take that SAME working query and save it in Access as a pass-through query.

Then in Access you can append to a table in Access (assuming same table structure with:

VBA (Access code)

Dim strSQL as string
strSQL = "INSERT INTO LocalTable SELECT * from QryPassR"
Currentdb.Execute strSQL

And if you want to MAKE a new table in Access with the SAME structure, so make table (not append), you can go:

Dim strSQL as string
strSQL = " SELECT * INTO LocalTable FROM qryPassR"
Currentdb.Execute strSQL

You can also in VBA code change the PostgreSQL to include criteria for that select.

(air code - does not take into account SQL injection issue).

Dim strCity as string.

strCity = inputbox("What city to pull from PostGres?")

dim strSQL as string

strSQL = "select * from tbleHotels where City = '" = strCity & "'"

With currentdb.QueryDefs("QryPassR"
  .SQL = strSQL
End with
strSQL = "INSERT INTO LocalTable SELECT * from QryPassR"
Currentdb.Execute strSQL

‘ above will copy all the records from PostGreSQL of city = Edmonton into the Access table (called local table in this example).

And as noted, you not limited to “LocalTable” being a access table, it could be a FoxPro table, MySQL, SQL server etc. So you not limited to JUST using Access tables in the above with your given SQL. So any linked table you have in Access can be used – including ones that point to other database systems.

If you must use .net, then you have to:

Connect to first database. Execute query to pull and fill a datatable.

Connect to second database. Create (open) a data table based on second database.

Loop (iterate) each row from first connection datatable and copy the row into the second datatable (based on 2nd connection).

You have to do a row by row copy. (but there is ImportRow method of the .net datatable, so you don’t have to loop by a column by column copy. (but you have to loop row by row).

In Access this looping is not required and in fact you can use SQL commands that operate on both tables, including as per above the make table and append, and you can even do relation joins between such tables - even those based on different connections (data sources).

Edit

Based on comments, it looks like the simple question is:

After I insert a row into Access, how can I get the last ID (identity) of that insert?

The follow vb.net code will do this: Imports System.Data.OleDb

Dim MyCon As New OleDb.OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Test2\test44.accdb")
MyCon.Open()
Dim strSQL As String = "insert into tblHotels2 (City) VAlues('Edmonton')"
Dim cmd As New OleDb.OleDbCommand(strSQL, MyCon)
Dim r As Integer
cmd.ExecuteNonQuery()
cmd.CommandText = "select @@IDENTITY"
r = cmd.ExecuteScalar
Debug.Print(r)

Output = last PK id (autonumber)

Albert D. Kallal
  • 42,205
  • 3
  • 34
  • 51
  • His question states nothing about returning the last identify insert. (select @@ identity is supported in Access but the posters question states nothing about that issue at all. The question stated is selecting from Postgres, and hten the posted statement is a insert into. So it not at all clear here, but I read the question as to how to pull data from Postgre and insert into Access. select @idenifty from C# on a access database after a insert is supported anyway. – Albert D. Kallal Mar 09 '19 at 03:23
  • see my edit - it shows how to grab the ID of the last insert in .net. – Albert D. Kallal Mar 09 '19 at 04:24
  • 1
    SQLite is nice if you need a file based database (like ACE/JET). Only reason to use ACE would be if that is where the data is placed, coming from or resides already. And of course using Access is great if you have more then one connection to different database since you can use sql against those different data sources in one command - something that tends to be a real pain in most systems. If user has choice of where data is to reside, then SQLite, ACE etc. really is a choice of flavor of the day. It really depends on where the original data resides and if developer has that choice. – Albert D. Kallal Mar 09 '19 at 04:36
  • Seems like you can use different connections in`.Net`with ACE.OleDB too. Just define the other connections inside the query like in [Select data from an ODBC connection into a MS Access database](https://stackoverflow.com/a/40092175/9439330) – ComputerVersteher Mar 09 '19 at 05:59
  • Well, you can’t use a conection to MySQL and Oracle in .net and have the SQL join the data. Of course if you going to introduce non managed code and introduce ACE/JET into this mix, then yes that is my whole point – the Access ACE engine can be used since it has the ability to connect between different sources – something .net can’t do. So if you ignore the connection abilities of .net and use ACE with given ACE connections then you can do this but you NOT be using the .net connection object anymore. – Albert D. Kallal Mar 09 '19 at 18:33