How to use variable (datatable) in sql command text to execute - sql

I am new to Vertica and trying this in angular aspx page.
`con.Open();
cmd = con.CreateCommand();
cmd.Connection = con;
cmd.Parameters.Add(new VerticaParameter("#tblCustomers", table));
cmd.CommandText = "insert into customers select * from #tblCustomers";
cmd.ExecuteNonQuery();`
I have established the connection and inserted some fresh records too.
But Now I am trying to insert bulk records in my vertica database's table.
Something Same like SqlServer,
I have loaded my table data into "table" variable. Which is a datatable.
Is it possible to do like this ?? As I am getting some error
"
Incorrect syntax at or near $1"
customers and #tblCustomers both have same columns.
Thanks!

Setting aside whether or not you should do something like this, in the code that you've posted you're passing #tblCustomers as a parameter to the query, so it's going to treat it as a string value, not an object name in the query. You need to build the CommandText in your code without that as a parameter. Something like:
cmd.CommandText = "insert into customers select * from " & tableName
(Sorry if that syntax isn't quite right, but hopefully it gets across the point)
Some additional (and important) notes though:
Always use a column list when doing an INSERT. Use INSERT INTO MyTable (some_column, some_other_column) SELECT... not INSERT INTO MyTable SELECT...
NEVER use SELECT *. List out your column names.

Related

Access VBA dump recordset into an existing table

I have a recordset and a table, both in exactly the same format. What is the syntax to dump everything in the recordset to the table? This seems to be a very simple procedure but somehow I can't find any useful information online.
Edit1: to clarify, the recordset is obtained from Table A, now I want to dump it into Table B (which is empty). Table A and B have exactly the same format.
Edit2: I am working in Access.
here is the code I used to open the recordset:
Set Table_B_rs = CurrentDb.OpenRecordset("Table_B")
I didn't make any changes to the recordset.
Thanks for the help!
You don't do this with recordsets, but with SQL by running an INSERT INTO query.
CurrentDb.Execute "INSERT INTO TableB SELECT * FROM TableA " & _
"WHERE <same conditions you used to open the recordset>"
If there is no condition, it's simply
CurrentDb.Execute "INSERT INTO Table_B SELECT * FROM Table_A"

Derby SELECT statement failing to find a specific string

I have a table that contains a column called ATEST, in a schema called TESTSCHEMA, that is in a database called SESSION.
I am trying to find records whose ATEST column has a string called "MyTest".
I am using the following SQL:
final String query = "SELECT * FROM SESSIONDATA.SESSIONS WHERE SESSION.TESTSCHEMA.ATEST = 'MyTest'";
Now I have placed several records whose ATEST column contains "MyTest". I use JDBC in the usual way:
device = aConnect.prepareCall(query);
ResultSet result = device.executeQuery();
Note that, for brevity, try and catch code is being omitted since I am not getting any exceptions thrown.
For some reason, I keep getting what amounts to empty result sets. I cannot get this statement to find any records despite the fact that I have several records in the database where ATEST = 'MyTest'!
Have I found a bug in Derby? Searches without WHERE clauses or where WHERE clauses look for numbers seem to work without problems. Why doesn't a WHERE clause that looks for a string find the strings, despite the fct that the strings are actually in the database???
Someone please advise.
Try sending like
final String query = "SELECT * FROM SESSIONDATA.SESSIONS WHERE SESSION.TESTSCHEMA.ATEST = '''MyTest'''";
It should hit DB like
SELECT * FROM SESSIONDATA.SESSIONS WHERE SESSION.TESTSCHEMA.ATEST = 'MyTest'
instead of
SELECT * FROM SESSIONDATA.SESSIONS WHERE SESSION.TESTSCHEMA.ATEST =MyTest
I don't know Derby. But your query looks strange:
You say the database is called SESSION. So this is where you connect to. I wouldn't expect it's name in a query.
Your schema is called TESTSCHEMA. So this is where the tables reside in. ATEST is a column. So aren't you missing the table name between schema and column in TESTSCHEMA.ATEST?
You select from SESSIONDATA.SESSIONS. What is SESSIONDATA suddenly? It's neither of the names you mentioned. What is SESSIONS? Is that the table name?
I would expect a query about like this:
SELECT * FROM testschema.sessions WHERE atest = 'MyTest'
(Where the schema name might even be superfluous in case it's the default schema for your connection.)
Try using a numeric value for referencing in place of 'Mytest'
Replace
SELECT * FROM SESSIONDATA.SESSIONS WHERE SESSION.TESTSCHEMA.ATEST = 'MyTest'
with
SELECT * FROM SESSIONDATA.SESSIONS WHERE SESSION.TESTSCHEMA.ATEST = 123

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.

What does a question mark represent in SQL queries?

While going through some SQL books I found that examples tend to use question marks (?) in their queries. What does it represent?
What you are seeing is a parameterized query. They are frequently used when executing dynamic SQL from a program.
For example, instead of writing this (note: pseudocode):
ODBCCommand cmd = new ODBCCommand("SELECT thingA FROM tableA WHERE thingB = 7")
result = cmd.Execute()
You write this:
ODBCCommand cmd = new ODBCCommand("SELECT thingA FROM tableA WHERE thingB = ?")
cmd.Parameters.Add(7)
result = cmd.Execute()
This has many advantages, as is probably obvious. One of the most important: the library functions which parse your parameters are clever, and ensure that strings are escaped properly. For example, if you write this:
string s = getStudentName()
cmd.CommandText = "SELECT * FROM students WHERE (name = '" + s + "')"
cmd.Execute()
What happens when the user enters this?
Robert'); DROP TABLE students; --
(Answer is here)
Write this instead:
s = getStudentName()
cmd.CommandText = "SELECT * FROM students WHERE name = ?"
cmd.Parameters.Add(s)
cmd.Execute()
Then the library will sanitize the input, producing this:
"SELECT * FROM students where name = 'Robert''); DROP TABLE students; --'"
Not all DBMS's use ?. MS SQL uses named parameters, which I consider a huge improvement:
cmd.Text = "SELECT thingA FROM tableA WHERE thingB = #varname"
cmd.Parameters.AddWithValue("#varname", 7)
result = cmd.Execute()
The ? is an unnamed parameter which can be filled in by a program running the query to avoid SQL injection.
The ? is to allow Parameterized Query. These parameterized query is to allow type-specific value when replacing the ? with their respective value.
That's all to it.
There are several reasons why it's good practice to use Parameterized Queries. In essence, it's easier to read and debug, and circumvents SQL injection attacks.
It's a parameter. You can specify it when executing query.
I don't think that has any meaning in SQL. You might be looking at Prepared Statements in JDBC or something. In that case, the question marks are placeholders for parameters to the statement.
It normally represents a parameter to be supplied by client.

Select the last row in a SQL table

Is it possible to return the last row of a table in MS SQL Server.
I am using an auto increment field for the ID and i want to get the last one just added to join it with something else. Any idea?
Here's the code:
const string QUERY = #"INSERT INTO Questions (ID, Question, Answer, CategoryID, Permission) "
+ #"VALUES (#ID, #Question, #Answer, #CategoryID, #Permission) ";
using (var cmd = new SqlCommand(QUERY, conn))
{
cmd.Parameters.AddWithValue("#Question", question);
cmd.Parameters.AddWithValue("#Answer", answer);
cmd.Parameters.AddWithValue("#CategoryID", lastEdited);
cmd.Parameters.AddWithValue("#Permission", categoryID);
cmd.ExecuteNonQuery();
}
Not safe - could have multiple inserts going on at the same time and the last row you'd get might not be yours. You're better off using SCOPE_IDENTITY() to get the last key assigned for your transaction.
using an auto increment field ... and i want to get the last one just added to join it with something else.
The key here is "just added". If you have a bunch of different users hit the db at the same time, I don't think you want user A to retrieve the record created by user B. That means you probably want to use the scope_identity() function to get that id rather than running a query on the table again right away.
Depending on the context you might also need ##identity (would include triggers) or ident_current('questions') (limited to a specific table, but not the specific scope). But scope_identity() is almost always the right one to use.
Here's an example:
DECLARE #NewOrderID int
INSERT INTO TABLE [Orders] (CustomerID) VALUES (1234)
SELECT #NewOrderID=scope_identity()
INSERT INTO TABLE [OrderLines] (OrderID, ProductID, Quantity)
SELECT #NewOrderID, ProductID, Quantity
FROM [ShoppingCart]
WHERE CustomerID=1234 AND SessionKey=4321
Based on the code you posted, you can do something like this:
// don't list the ID column: it should be an identity column that sql server will handle for you
const string QUERY = "INSERT INTO Questions (Question, Answer, CategoryID, Permission) "
+ "VALUES (#Question, #Answer, #CategoryID, #Permission);"
+ "SELECT scope_identity();";
int NewQuestionID;
using (var cmd = new SqlCommand(QUERY, conn))
{
cmd.Parameters.AddWithValue("#Question", question);
cmd.Parameters.AddWithValue("#Answer", answer);
cmd.Parameters.AddWithValue("#CategoryID", lastEdited);
cmd.Parameters.AddWithValue("#Permission", categoryID);
NewQuestionID = (int)cmd.ExecuteScalar();
}
See my answer to another question here:
get new SQL record ID
The problem now is that you'll likely want subsequent sql statements to be in the same transaction. You could do this with client code, but I find keeping it all on the server to be cleaner. You could do that by building a very long sql string, but I tend to prefer a stored procedure at this point.
I'm also not a fan of the .AddWithValue() method — I prefer explicitly defining the parameter types — but we can leave that for another day.
Finally, it's kind of late now, but I want to emphasize that it's really better to try to keep this all on the db. It's okay to run multiple statements in one sql command, and you want to reduce the number of round trips you need to make to the db and the amount of data you need to pass back and forth between the db and your app. It also makes it easier to get the transactions right and keep things atomic where they need to be.
use
scope_identity() returns the last identity value generated in this session and this scope
ident_current() returns the last identity value generated for a particular table in any session and any scope
select ident_current( 'yourTableName' )
will return the last identity created by a different session.
Most of the time you should use scope_identity() right after an insert statement like so.
--insert statement
SET #id = CAST(SCOPE_IDENTITY() AS INT)
MSDN Link - Scope_Identity()
MSDN Link - Ident_Current
select top 1 * from yourtable order by id desc
I'm not sure of your version of SQL Server, but look for the OUTPUT clause of ther INSERT statement. You can capture a set of rows with this clause
Since the questioner is using .NET, here's a modified example of how to do it. (I removed ID from the insert list since it's autoincrement--the original example would fail. I also assume ID is an SQL int, not a bigint.)
const string QUERY = #"INSERT INTO Questions (Question, Answer, CategoryID, Permission) "
+ #"VALUES (#Question, #Answer, #CategoryID, #Permission);"
+ #"SELECT #ID = SCOPE_IDENTITY();";
using (var cmd = new SqlCommand(QUERY, conn))
{
cmd.Parameters.AddWithValue("#Question", question);
cmd.Parameters.AddWithValue("#Answer", answer);
cmd.Parameters.AddWithValue("#CategoryID", lastEdited);
cmd.Parameters.AddWithValue("#Permission", categoryID);
cmd.Parameters.Add("#ID", System.Data.SqlDbType.Int).Direction = ParameterDirection.Output;
cmd.ExecuteNonQuery();
int id = (int)cmd.Parameters["#ID"].Value;
}
EDITED: I also suggest considering LINQ to SQL instead of hand-coding SqlCommand objects--it's much better (faster to code, easier to use) for many common scenarios.
With a simple select you can do something like this:
SELECT *
FROM table_name
WHERE IDColumn=(SELECT max(IDColum) FROM table_name)