Datagridview - Oracle Update error "Dynamic SQL generation failed." - sql

I'm using Datagridview to show me joined records from 2 tables. Data that is showing is from one of the tables + data that are in joined table (Table3). SQL query returns results in Datagridview (works fine in Oracle too), but update fails with "Dynamic SQL generation failed. Either no base tables were found or more than one base table was found". Here is my table design:
Table1:
ID_TABLE1
ITEM_NAME
ITEM_DESCRIPTION
Table3: (this is a joined view for Table1 and Table2)
ID_TABLE3
ID_TABLE1_FK
ID_TABLE3_FK
VALIDITY
DATE_CONNECTION
My code (exactly as Oracle recommends):
Public Class Form2
Private da As OracleDataAdapter
Private cb As OracleCommandBuilder
Private ds As DataSet
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Saving.Enabled = False 'this deals with error with updating (from Oracle site)
Dim SQL As String = "SELECT ID_TABLE1, ID_TABLE3, SERIAL_NO, ITEM_NAME, ITEM_DESCRIPTION, VALIDITY, DATE_CONNECTION from TABLE1, TABLE2 WHERE TABLE3.ID_TABLE1_FK=" & Form1.DataGridView1.CurrentRow.Cells(0).Value.ToString
Try
Oracleconn() 'connection to my DB
Dim cmd = New OracleCommand(SQL, Oracleconn)
cmd.CommandType = CommandType.Text
da = New OracleDataAdapter(cmd)
cb = New OracleCommandBuilder(da)
ds = New DataSet()
da.Fill(ds)
My_DGV.DataSource = ds.Tables(0)
Saving.Enabled = True
Catch ex As Exception
MessageBox.Show(ex.Message)
Finally
'No closing of connection here because of working with Dataset (Oracle suggestion)
End Try
End Sub
Private Sub Saving
da.Update(ds.Tables(0))
Saving.Enabled = True
End Sub
End Class
So, Is my SQL query wrong or what ? Any help would be much appreciated !
P.S.: In actual case only column "VALIDITY" from Table3 will be allowed to change for users, so I need to update only that field.

This is too complicated for me, looks like Oracle-provided suggestion for working with Datasets just isn't easy when you want to perform Update on join table records. So I tried a different approach and It worked for me. Since what I need is to update only 1 column from SQL query which returns to Datagridview I did this :
For Each row As DataGridViewRow In My_.Rows
cmd.Parameters.Add(New OracleParameter("validity", row.Cells(6).Value))
cmd.CommandText = "UPDATE TABLE3 SET VALIDITY= : validity WHERE ID_TABLE1_FK='" & row.Cells(1).Value & "'"
cmd.ExecuteNonQuery()
cmd.Parameters.Clear()
Next
If anyone knows the answer to my original question - so how to do same with just da.Update(ds.Tables(0)), then please let me know. I reckon that SQL query needs to be properly changed, using JOIN method.

Related

Fill combobox starting from the second record

I Fill My ComboBox1 From Field ( Drivers ) ..with this code all records appears in Combobox1 .. How to make so that the first record does not appear in ComboBox1 .. i want the records to start with the second records in my combobx1 .. the ID numbers are (1-2-3-4-5-6) and so on.
Private Sub Fill_Numeros_Drivers()
Dim InfoAdapter As OleDbDataAdapter
Dim InfoTable As DataSet
ComboBox1.Items.Clear()
Dim Sql As String = "SELECT DISTINCT Drivers From Table1"
InfoAdapter = New OleDbDataAdapter(Sql, Conne)
InfoTable = New DataSet
InfoTable.Clear()
InfoAdapter.Fill(InfoTable, "Table1")
For Each rw As DataRow In InfoTable.Tables("Table1").Rows
ComboBox1.Items.Add(rw(0).ToString())
Next
End Sub
Keep your database objects local so you control their closing and disposing. Using...End Using blocks will do that for you even if there is and error.
I added a field to the query for DriverID. Whatever your Primary Key field is might be appropriate to assure the order of the records. The field in the Order By clause must be in the Select part of the query when DISTINCT is used. This field is downloaded but never used.
The first call to reader.Read reads the first record but nothing is done with it. The second call to reader.Read is now on the second record.
Private Sub Fill_Numeros_Drivers()
Using Conne As New OleDbConnection("Your connection string")
Using cmd As New OleDbCommand("SELECT DISTINCT Drivers, DriverID From Table1 Order By DriverID", Conne)
Conne.Open()
Using reader As OleDbDataReader = cmd.ExecuteReader
reader.Read() 'Reads the first record
Do While reader.Read
ComboBox1.Items.Add(reader.GetString(0))
Loop
End Using
End Using
End Using
End Sub

Executing delete command on MS-Access through VB.NET does not delete the records

Just trying to delete all rows of an Access table:
Private Sub btnImport_Click(sender As Object, e As EventArgs) Handles btnImport.Click
'Clear old records from extract table
Dim sqlConnection As New System.Data.OleDb.OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\CLI_CRVM.accdb")
Dim cmd As New System.Data.OleDb.OleDbCommand()
Dim intRC As Integer
cmd.CommandType = System.Data.CommandType.Text
cmd.CommandText = "DELETE * FROM [extract] ;"
cmd.Connection = sqlConnection
sqlConnection.Open()
intRC = cmd.ExecuteNonQuery()
sqlConnection.Close()
MsgBox(intRC)
End Sub
I do not get any errors but it doesn't delete the rows either. There are currently 10 rows in the table and the MsgBox shows 10 each time the button is clicked and there are still 10 rows in the table afterwards.
What am I missing?
Try without the asterisk:
DELETE FROM [extract];
You don't generally supply any columns in a DELETE. You only supply columns that you want to match a row against .. via a WHERE clause afterwards.
There are certain dialects of SQL that let you specify thresholds on what you delete in that part of the query - however, I don't believe Access' dialect does (I could be wrong).

Convert Access Query to VB.net SQL Statement

I have a table in my Access database called Historical_Stock_Prices that is filled with various companies historical stock prices. I need to run a query that will convert the raw data (the stock prices) into quarterly growth rates and display the quarterly growth rates in a DataGridView.
I've already written the the following query in the SQL View of my Access database and it works within Access.
SELECT MinMaxYrQtrDates.YrQtr, MinMaxYrQtrDates.Ticker, MinMaxYrQtrDates.MaxDate, [Historical Prices].Close, MinMaxYrQtrDates.MinDate, [Historical Prices_1].Open, ([Historical Prices].[Close]/[Historical Prices_1].[Open]-1)*100 AS GrowthRate
FROM [Historical Prices] AS [Historical Prices_1] INNER JOIN ([Historical Prices] INNER JOIN [SELECT Year([Date]) & "-" & DatePart("q",[Date]) AS YrQtr, [Historical Prices].Ticker, Max([Historical Prices].Date) AS MaxDate, Min([Historical Prices].Date) AS MinDate
FROM [Historical Prices]
GROUP BY Year([Date]) & "-" & DatePart("q",[Date]), [Historical Prices].Ticker]. AS MinMaxYrQtrDates ON ([Historical Prices].Date = MinMaxYrQtrDates.MaxDate) AND ([Historical Prices].Ticker = MinMaxYrQtrDates.Ticker)) ON ([Historical Prices_1].Ticker = MinMaxYrQtrDates.Ticker) AND ([Historical Prices_1].Date = MinMaxYrQtrDates.MinDate);
I need to be able to call it from within my program and display the results in a DataGridView. I've tried to copy the SQL statement from Access and use it as the SQL statement in my code but it doesn't work. I don't get any errors, the DataGridView is just blank. Here is my code so far:
Imports System.IO
Imports System.Data.OleDb
Public Class Historical_Growth_Rates_Annual
Public tblName As String = "Historical_Stock_Prices"
Private Sub Historical_Growth_Rates_Annual_Load(sender As Object, e As EventArgs) Handles MyBase.Load
If (File.Exists(Nordeen_Investing_3.databaseName)) Then
Nordeen_Investing_3.con.Open()
Dim restrictions(3) As String
restrictions(2) = tblName
Dim dbTbl As DataTable = Nordeen_Investing_3.con.GetSchema("Tables", restrictions)
If dbTbl.Rows.Count = 0 Then
MessageBox.Show("Historical Stock Prices tables does not exist in the database. Please Update")
Else
Dim da As OleDbDataAdapter = New OleDbDataAdapter("SELECT MinMaxYrQtrDates.YrQtr, MinMaxYrQtrDates.Ticker, MinMaxYrQtrDates.MaxDate, [Historical_Stock_Prices].Close1, MinMaxYrQtrDates.MinDate, [Historical_Stock_Prices_1].Open1, ([Historical_Stock_Prices].[Close1]/[Historical_Stock_Prices_1].[Open1]-1)*100 AS GrowthRate FROM [Historical_Stock_Prices] AS [Historical_Stock_Prices_1] INNER JOIN ([Historical_Stock_Prices] INNER JOIN [SELECT Year([Date1]) & " - " & DatePart('q',[Date1]) AS YrQtr, [Historical_Stock_Prices].Ticker, Max([Historical_Stock_Prices].Date) AS MaxDate, Min([Historical_Stock_Prices].Date) AS MinDate FROM [Historical_Stock_Prices] GROUP BY Year([Date1]) & " - " & DatePart('q',[Date1]), [Historical_Stock_Prices].Ticker]. AS MinMaxYrQtrDates ON ([Historical_Stock_Prices].Date = MinMaxYrQtrDates.MaxDate) AND ([Historical_Stock_Prices].Ticker = MinMaxYrQtrDates.Ticker)) ON ([Historical_Stock_Prices_1].Ticker = MinMaxYrQtrDates.Ticker) AND ([Historical_Stock_Prices_1].Date = MinMaxYrQtrDates.MinDate);", Nordeen_Investing_3.con)
'create a new dataset
Dim ds As New DataSet()
'fill the datset
da.Fill(ds)
'attach dataset to the datagrid
DataGridView1.DataSource = ds.Tables(0)
ds = Nothing
da = Nothing
Nordeen_Investing_3.con.Close()
End If
Else
MessageBox.Show("Database does not exist. Please update.")
End If
End Sub
End Class
I'm really stuck and could use some help! Thanks!
You want that VB.Net code to recreate the same SELECT statement which works in Access. However, looking at the syntax highlighting with Vim, I think you may actually be creating something else. (It may be like creating a string as the difference of 2 other strings: "string 1" - "string 2").
But whether or not I guessed correctly, use a string variable to hold your SELECT statement. Then print that string to the console or write it to a text file so that you can examine the actual statement you're giving to the db engine.
Or save the working query in Access as a named query object and use that query name from your VB.Net code --- that would absolutely guarantee using the same SQL which is confirmed to work in Access.

Query for sum of column values not giving me a value

I have a GridView in my ASP Page where the user can change one of the values and the other is a read only value. I want that when the row is updated a query will execute that sums the value of one column to the other and changes it. Ex... Value1 + Value 2 = Value2. I wrote this in the code-behind:
Protected Sub GridView1_RowUpdated(sender As Object, e As EventArgs) Handles GridView1.RowUpdated
Dim connectionString As String = "mystring"
Using cn As New SqlConnection(connectionString)
Dim cmd As New SqlCommand()
cmd = New SqlCommand("Select (Purchased + Actual) as Actual from Product", cn)
cn.Open()
cmd.ExecuteNonQuery()
cn.Close()
End Using
yet the value doesn't sum. A part of me says I need an update command to save the value or something like that but what I read in W3 and other places doesn't point me to that. I guess since there's different products (of course) I need a WHERE ProductID = #Parameter... right? Still that code should change the rest of the values and it doesn't. Any pointers or anything that flew over me? Thanks a bunch!
Looks like you want
Update Product Set Value2 = Value1 + Value2
Where ProductId = #Parameter

Select Statement SQL in VB

I understand that there are other posts such as this, however I cannot find one that will work for me and Im really at the end of my tether with this, I really dont know what to do.
I have a few tables with ID columns and name columns, that are connected by Link Tables through foreign keys etc. I'm trying to enter data into the database via a GUI and to do so I'm using insert statements into the 'regular' tables, then Select statements to get the autogen IDs from the regular table to then insert into the link tables.
The code below is what I've been trying to use to do this.
Imports System.Data.SqlClient
Public Class Test
Private cs As New SqlConnection(".....")
Private Sub btnInsertNext_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnInsertNext.Click
Dim ContID As Integer
Dim FName As Integer
cs.Open()
Using command As New SqlCommand("Select FamID From Family Where Name = '" & FName & " '", cs)
command.Parameters.AddWithValue("#FamID", ContID)
command.ExecuteNonQuery()
End Using
Using command As New SqlCommand("Select DocID From Doctors Where DocName LIKE'" & AddFam.Doctor & " '", cs)
command.Parameters.AddWithValue("#DocID", AddFam.Doctor) ''AddFam is another form I'm using to add a family member to a Doctor
command.ExecuteNonQuery()
End Using
cs.close()
I'm using:
VB 2010
SQL server management 2008 r2
I understand its a bit muddley but any help would be greatly appreciated, and I'm sorry if this has come up before.
It's not really clear what problem you actually have, i assume that you don't know how to retrieve newly generated IDs.
Here is an self-explanatory example on how to retrieve new identity values with ADO.NET:
Using con = New SqlConnection(connectionString)
Dim newID As Int32
Using insertCommand = New SqlCommand("INSERT INTO Test(Value)VALUES(#Value);SELECT CAST(scope_identity() AS int)", con)
insertCommand.Parameters.AddWithValue("#Value", "Value1")
con.Open()
newID = DirectCast(insertCommand.ExecuteScalar, Int32)
End Using
If newID <> 0 Then
Using updateCommand = New SqlCommand("UPDATE TEST SET Value='Value1.1' WHERE idTest=#idTest", con)
updateCommand.Parameters.AddWithValue("#idTest", newID)
If con.State <> ConnectionState.Open Then con.Open()
Dim updatedRecordCount = updateCommand.ExecuteNonQuery
End Using
End If
End Using
The 2 important parts are:
SELECT CAST(scope_identity() AS int)
which will return the new identity value
DirectCast(insertCommand.ExecuteScalar, Int32)
which will return the new Identity column value if a new row was inserted, 0 on failure.
Since you're mixing using parameters with string-concatenation: using parameters is very important because it will prevent SQL-Injection.
SCOPE_IDENITY
ExceuteScalar-Method
Commands and Parameters in ADO.NET
NO! Parameterise your queries like this.
command = New SqlCommand("Select FamID From Family Where Name = #Fname", cs)
command.Parameters.AddWithValue("#Fname", ContID)
FamID = command.ExecuteScalar()
And ideally, you should use Scope_Identity() to get the Identity from you insert statement
You can try with this code on two queries based on # symbol
...
Using command As New SqlCommand("Select FamID From Family Where Name = #FamID", cs)
command.Parameters.AddWithValue("#FamID", ContID)
...
Using command As New SqlCommand("Select DocID From Doctors Where DocName LIKE #DocID", cs)
command.Parameters.AddWithValue("#DocID", AddFam.Doctor)
...