Operation must use and updatable query. (Error 3073) - sql

What is wrong with my logic below, is there any alternative to get calculatable column which will sum Balances for every unique KEY ?
Purpose: To create a summary column, calculation of Balances for each unique Key created ( Sort Code + Source Account) which will be used later to define whether acc type is Dr/Cr.
Code: below code should create summary column , but every time it triggers error depicted in attached screenshot.
***' Creating Sum of Balances based on Key , to differtiate Dr/Cr Account types
DoCmd.RunSQL "ALTER TABLE Output_File ADD Summing varchar(255)"
DoCmd.RunSQL "UPDATE Output_File SET Summing =" _
& "(SELECT SUM(Output_File.CURR_VALUE)" _
& " FROM Output_File GROUP BY Output_File.`UNIQUE KEYS`)"***
Error:
Error

In MS Access SQL, update queries must be updateable or not read-only. Any use of subqueries renders the query read-only. See Allen Browne's Why is my query read-only? One workaround is to use domain aggregates such as DSum available in Access SQL and VBA.
Ideally, too, consider using a saved query and avoid the need of building long SQL statements in VBA and have to worry about line breaks and concatenations. Below assumes UNIQUE KEYS is a number field. If text field, wrap in single quotes. If a date field, wrap in hashtags/pound symbols.
SQL (save as stored query)
UPDATE Output_File o
SET Summing = DSum("CURR_VALUE", "Output_File", "`UNIQUE KEYS` = " & o.`UNIQUE KEYS`)
VBA (reference above saved query)
DoCmd.OpenQuery "mySavedQuery" ' NO NEED TO CLOSE ACTION QUERIES
CurrentDb.Execute "mySavedQuery" ' ALTERNATIVE CALL

Related

Is that possible that access to a sql table with question mark?

I have 3 sql tables customer, employee and manager. I want to access dynamically to my tables. I had a statement like this,
"update customer set AMOUNT where ID= ?"
But in this situation i can only access to customer. I need to access all of the tables for different operations. Is that possible to write this,
"update ? set AMOUNT where ID=?"
or what can i do to access for example employee for a different class.
The parameters can be used only in the place where you could otherwise use a literal value, like a quoted string or a numeric value.
Parameters cannot be used for identifiers like table names. Nor expressions. Nor SQL keywords.
All those other parts of the query must be fixed in the SQL query string before you prepare the query.
To query other tables, you just have concatenate the table name into the string.
String query = "update " + tableName + " set amount where ID=?";
It's up to you to make sure your variable tableName in fact only contains one of your table names. A good way to do this is to compare it to a list of known table names, and if it isn't in the list, throw an exception.

deleting records with parameter

how do you add a parameter after this code so that I can delete the records ininteger data type: here is the code.
com = New OleDbCommand("DELETE * FROM Products WHERE Product = '" & DataGridView1.CurrentRow.Cells(0).Value.ToString & "'", con1)
I keep getting a message that the data type is mismatched
You have no WHERE clause in your SQL code. If you don't specify a WHERE clause then you are referring to every record. You have to use the WHERE clause to specify WHICH record to update. That's what the primary key is for.
You must need a Where clause in your SQL Statement to distinct the row for edit else it can change all.
You must use where clause in that it update only that record which you want..if you don't use where clause it update all records.
for more information of update you use this link

Adding ' at the start of each row of a table through sql

I have a column called "product-code". These are all populated. I am wanting to do a query that will insert a ' at the start of each field and then another query to add a ' at the end of the field.
So for example at the moment a product code might be fmx-2, after the query I would want it to look like 'fmx-22'
I am looking to do this for all the data sets within the table. I am using Microsoft Access
Thanks
In Microsoft Access you can use & char to concatenate string, and your query could be something similar:
update my_table set product_code = "'" & product_code & "'";

Unable to select values when using a parameter for the column name

Try
Using connection As New SqlConnection(ConnectionString)
connection.Open()
SQL = "SELECT #PARAM FROM SystemOps"
sqlCmd = New SqlClient.SqlCommand(SQL, connection)
sqlCmd.Parameters.Add(New SqlClient.SqlParameter("#PARAM", SqlDbType.VarChar)).Value = "SystemNavn"
' .. and so on...
When I run the code, it returns with a result of "SystemNavn" (which is the name of the column in the table), instead of the value of that column in the current row. What am I doing wrong?
You cannot use parameter names for column names, or any other SQL syntax. You can only use parameters as placeholders for literal values. Parameters always get replaced with the literal form for the value, so in your example, the command which is being run, essentially, gets evaluated as:
SELECT 'SystemNavn` FROM SystemOps
In order to have a variable column name, like that, I would recommend dynamically building the SQL string, like this:
Dim columnName As String = "SystemNavn"
SQL = "SELECT [" & columnName & "] FROM SystemOps"
However, by doing so, you are opening yourself up to potential SQL-injection attacks, so you need to be careful. The safest way, that I'm aware of, to avoid an attack in a situation like this is to get the list of column names from the database and compare the columnName variable against that list to ensure that it is actually a valid column name.
Of course, if the column name never changes, then there's no reason to make it a variable at all. In that case, just hard-code it directly into the SQL command, thereby avoiding the necessity for parameters or variables at all:
SQL = "SELECT SystemNavn FROM SystemOps"
Your query doesn't need any parameters in this case. just do
SQL = "SELECT SystemNavn FROM SystemOps"
This is secure. If later you need to filter this, you can do something like:
SQL = "SELECT SystemNavn FROM SystemOps WHERE COL_A = #ColA"
FYI, for your code above, since it is a VARCHAR type, it is being executed like so:
SELECT 'SystemNavn' FROM SystemOps
That is why you're getting 'SystemNavn' back.
You cannot use a parameter to specify the name of a column or a table.
The parameters collection are used to specify the values to search for, to insert, to update or delete.
Your code should be changed to something like this
Using connection As New SqlConnection(ConnectionString)
connection.Open()
SQL = "SELECT SystemNavn, <other fiels if needed> " & _
"FROM SystemOps WHERE <keyfield_name> = #PARAM"
sqlCmd = New SqlClient.SqlCommand(SQL, connection)
sqlCmd.Parameters.AddWithValue("#PARAM", paramValue)
......
End Using
Of course the example above assumes that you have a WHERE clause, if you want to retrieve every value of the column SystemNavn without condition, then you don't need a parametrized query because every part of your sql command is provided by you and there is no worry for sql injection.

SQL Query in Access to prompt with Message Box asking to change table name

Is there a way to be prompted before you a run an SQL query in Access, to enter in the table name that you wish to query? For example, lets say the columns will always stay constant. The columns could be called "Fruit" and "Date." But, the table name could change depending on the batch number. Ie. table name could be "BatchNO_1" or "BatchNO_2" or "BatchNO_3" etc. So Lets say i have an SQL like:
select Fruit, Date from BatchNO_1 where Fruit = "Apples"
Is there a way that I can be prompted to enter in the table name and have the SQL use the table name i enter to perform the query?
No. The table name cannot be passed as parameter to a query. You will have to construct the query yourself.
Dim tableName as String, sql As String
tableName = InputBox("Please enter the table name")
If tableName <> "" Then
sql = "SELECT Fruit, Date FROM [" & tableName & "] WHERE Fruit = 'Apples'"
'TODO: execute the query here
End If
For instance, you could change the query text of an existing query like this:
CurrentDb.QueryDefs("myQuery").SQL = sql
Or you could execute the query like this
Dim db As DAO.Database, rs As DAO.Recordset
Set db = CurrentDb
Set rs = db.OpenRecordset(sql)
Do Until rs.EOF
Debug.Print rs!Fruit & " " & rs!Date
rs.MoveNext
Loop
rs.Close: Set rs = Nothing
db.Close: set db = Nothing
By putting the batch number in the table name instead of as a column, you are encoding data in the schema. This is not best practice, so in my opinion, the correct answer is to change your database design.
Make a single Batch table with all the columns from your current BatchNo tables, but add a column named BatchNo as part of the primary key. Load all the data from your BatchNo tables into this one, and then delete those tables. Then your query will straightforwardly look like this:
SELECT Fruit, Date
FROM Batch
WHERE
Fruit = "Apples"
AND BatchNo = [Enter Batch No];
Don't put data in table names. That is not the way databases are supposed to be made.
Just to explain a little bit, the reason that your current design violates best practice is due to exactly the problem you are facing now--the shenanigans and weird things you have to do to work with such a design and try to perform operations in a reasonable, data-driven, way.
By having the user enter the table name, you also create the danger of SQL injection if you aren't also careful to compare the user-provided table name to a whitelist of allowed table names. While this may not be such a big deal in Access, it is still heading down the wrong path and is training for something else besides professional database work. If you would ever like to grow your career, it would be regrettable to first have to unlearn a bunch of stuff before you could even start with a "clean slate" to learn the right way to do things.