How to mimic the SQL Server VALUES feature in ACCESS? - sql-server

I have this SQL query in SQL Server
SELECT
v.val
FROM
(VALUES ('MONTROSE'), ('STERLING'), ('GREELEY'), ('FRED'), ('BILL')) v (val)
LEFT JOIN co_wtr t ON t.Quad = v.val
WHERE t.Quad IS NULL;
The point of the query is to find which of he VALUES are not in a table.
Need to run this type of query in ACCESS, but it does not have a VALUES feature. Any suggestions as how to do this in ACCESS.
The gotcha here is that the users don't have write privilege to the database. So the target set of values can't be put into a table.

Not easily, but you can use a UNION ALL query. We use MSysObjects, a default table, here. It can be replaced by any table that has at least one row and has a primary key.
SELECT v.val FROM
(
SELECT TOP 1 'MONTROSE' AS val FROM MSysObjects UNION ALL
SELECT TOP 1 'STERLING' FROM MSysObjects UNION ALL
SELECT TOP 1 'GREELEY' FROM MSysObjects UNION ALL
SELECT TOP 1 'FRED' FROM MSysObjects UNION ALL
SELECT TOP 1 'BILL' FROM MSysObjects
) v LEFT JOIN co_wtr t ON t.Quad = v.val
WHERE t.Quad IS NULL;
Note that we cannot omit the table, Access does do select queries without a FROM (e.g. SELECT 'A' is valid), but not unions of selects without a FROM (SELECT 'A' UNION ALL SELECT 'B' is not valid)
This leads to clunky queries, however. I'd reconsider if a temp table can't be used. Note that the table can be in Access, even though we join it with a linked table on SQL server, so only write permissions on the Access file are needed (and those are always needed to perform locking).

Comprehensive answer from #Erik A, nothing to add.
The method requires to form a string " ('MONTROSE'), ('STERLING'), ('GREELEY'), ('FRED'), ('BILL'))" in VBA and create dynamic query.
In the style inherent in MS Access, I may do the same
Dim OutList As Object
Set OutList = CreateObject("System.Collections.ArrayList")
With OutList
.Add "MONTROSE"
.Add "STERLING"
.Add "GREELEY"
.Add "FRED"
.Add "BILL"
End With
if CheckOutOffTable(OutList) then
...
endif
...
public function CheckOutOffTable( checkList as object) as boolean
Dim rst As Recordset
Set rst = CurrentDb.OpenRecordset("SELECT t.QUAD FROM co_wtr t GROUP BY t.QUAD")
Do While Not rst.EOF
If checkList.Contains(rst!Quad.Value) Then checkList.Remove rst!Quad.Value
rst.MoveNext
Loop
CheckOutOffTable=(checkList.Count>0)
end function
I like both approaches. Which is preferable in practice?

If this is a application that is linked to SQL server?
Then you could use a pass though query.
eg this:
dim strSQL as string
strSQL = "SELECT v.val FROM (VALUES ('MONTROSE'), ('STERLING'), ('GREELEY'), ('FRED'), ('BILL')) v (val) LEFT JOIN co_wtr t ON t.Quad = v.val"
currentdb.QueryDefs("qryPass").sql = strSQL
' now you can open a report, or form based on above query.

Related

SQL Insert parameter value and value from another table

I'm unable to find a solution online for my question. If it is even possible, how do I write an SQL Insert statement that uses parameter values as well as selecting a value from another table.
Example:
"INSERT INTO Users (user_name, user_csn, user_adid, user_contact, user_adminpriviledge, user_datestart, user_active, user_team)
VALUES (#username, #usercsn, #useradid, #usercontact, #userauth, #userstart, #useractive, #userteam = (SELECT team_id FROM teaminfo WHERE team_name = '" & ddlAddTeam.SelectedValue & "'))"
I understand that the example is wrong, just trying my best to represent what I'm looking for in code.
Also another question would be regarding aliasing and datareaders. I seem to be unable to do "reader("column_name")" for aliased column names?
Example:
query = "SELECT u.*, t.team_name FROM Users u
JOIN teaminfo t ON u.user_team = t.team_id WHERE user_csn = '" & GV.userCSN & "'"
I tried to use
reader("u.user_name")
but failed as well.
You need other syntax of insert operation: INSERT INTO ... SELECT ... FROM ...:
INSERT INTO Users (user_name, user_csn, user_adid, user_contact, user_adminpriviledge, user_datestart, user_active, user_team)
SELECT #username, #usercsn, #useradid, #usercontact, #userauth, #userstart, #useractive, team_id --<--not here's your column
FROM teaminfo
WHERE team_name = #param
Also, it looks like it's .NET (C# or VB code), so you you are prone to SQL injection concatenating you string with parameters!
In my SQL I already put #param in proper place, then with SqlCommand you are probably using, you have to call method Addon SqlCommand.Paramteres collection, and then supplly it with value of ddlAddTeam.SelectedValue.
Try this code:
Using connection = New SqlConnection("connString")
Using com = New SqlCommand
com.Connection = connection
com.CommandText = "INSERT INTO Users (user_name, user_csn, user_adid, user_contact, user_adminpriviledge, user_datestart, user_active, user_team)
Select #username, #usercsn, #useradid, #usercontact, #userauth, #userstart, #useractive, team_id --<--Not here's your column
From teaminfo
Where team_name = #param"
com.Parameters.Add("#param", SqlDbType.VarChar).Value = ddlAddTeam.SelectedValue
connection.Open()
End Using
End Using
And for column alises: in data reader you use column aliases without table name (u before the dot in ou example). Try to give aliases to all your columns to avoid such problems.
The data source for an INSERT statement can be a SELECT statement—see the <dml_table_source> part of the statement definition at the linked page—and a SELECT statement can include parameters in the select list. Here's a simple example:
declare #Target table (Id bigint, Datum char(1));
declare #Source table (Id bigint);
declare #Datum char(1) = 'X';
insert #Source values (1);
insert #Target
select
Id = S.Id, -- Value from another table
Datum = #Datum -- Parameter
from
#Source S;
There are more examples at the page linked above; scroll down to the "Inserting Data From Other Tables" section header.
Also, if you're going to build a query in (C#?) code as you've shown in your example, you should really pass any arguments as parameters rather than trying to build them directly into the query text. Read up on SQL injection attacks to see why.
Your INSERT query should be like
"INSERT INTO Users (user_name, user_csn, user_adid, user_contact, user_adminpriviledge, user_datestart, user_active, user_team)
VALUES (#username, #usercsn, #useradid, #usercontact, #userauth, #userstart, #useractive, (SELECT team_id FROM teaminfo WHERE team_name = #userteam ))"
Second when fetching from reader it should be like :
reader("user_name") // I am not sure about this. You can put break point and open the object in watch window

SQL SERVER: Loading data all at ONCE or Checking ONE by ONE?

Which one could be a better practice? In my situation, I need to check if a specific data exists in a table. I am iterating through an Excel file and verifying if a code there exists in my table using VB.NET. I have two options to do this (or if there is a better way to do this, I am open for suggestions).
First is to check it one by one, this code is executed per loop:
SQL = "SELECT TOP 1 * FROM Table1 WHERE Code = '" & codeFromExcel & "'"
rs = dbConn.Execute(SQL)
If Not rs.EOF Then
isFound = True
Else
isFound = False
End If
The other one is I load all the codes in a List(Of T)
Dim myList As New List(Of String)()
rs = Nothing
rs = dbConn.Execute("Select Code from Table1")
If Not rs.EOF Then
Do While Not rs.EOF
myList.Add(rs.Fields("Code").Value.ToString)
rs.MoveNext()
Loop
End If
Then check every record if it is in the List(Of T) while iterating in the Excel.
If myList.Contains(codeFromExcel) Then
isFound = True
Else
isFound = False
End If
I've been working with this kind of stuff most of the time and I want to know which one is the most efficient way to use. At the moment I only have a few records in my database. I want my code to be ready and efficient when the time comes that I need to deal with numerous records. Thanks in advance!
Additional info: The data doesn't need to be "fresh" as that table is meant for one-time entry only.
Personally I prefer to open as less connections to data base as possible.
So:
If the table is not very large (some hundred rows) I would go with the "cache" option.
Generally:
I would gather all excel codes in a list. ( excelCodes )
Then I would query something like Select Distinct Code from Table1 Where Code In ( excelCodesList ) and store it in a second list ( foundCodes ).
Then I would compare these lists.
I test it on a table with 6.143.993 rows.
To select just one column (description) to "cache" took 1'29".
On the other hand query like:
select distinct description from ItemDetail where description in ( 'abc','cddd','xxx' )
took 0'58".
UPDATE
An index on Code column might help with performance.

getting data from rows after executing query

I am very new to DB application development, though I have a fair amount of experience in VB.NET and C++ (self-taught, somewhat intermediate). I have a query in a table adapter with two parameters (user input) that always returns only one row from a table, based on those two parameters. Let's say row X with A, B and C columns. Filters are set on A and B in my query, but it selects all fields.
Now, I want to show the value of C in one of my main Form objects (let's say a Label in this example), but I cannot seem to be able to extract it. I know it probably is very easy, but I am a bit lost in DB code jungle..
[EDIT]
My apologies, the code bit (example).
Query:
SELECT Column1, Column2, Column3
FROM Table1
WHERE (Column1 = #Parameter1) AND (Column2 = #Parameter2)
In my VB project:
Dim temp
temp=Me.Table1TableAdapter.queryName(Me.MyProjectDBDataSet.Table1,userinput1, userinput2)
Up to this point everything works perfectly, but this is also where I get stuck. How do I, let's say, assign the value of Column3 (after running the query the result will always be only one row from Table1) to Label.Text for instance?
I hope this makes it a bit clearer..
Dim db As Database = DatabaseFactory.CreateDatabase
Dim cmd As DbCommand = db.GetSqlStringCommand(query) 'Query is a string containing your SQL command'
Dim sqlDataReader As IDataReader = db.ExecuteReader(cmd)
Dim myObj As New MyObject
If sqlDataReader IsNot Nothing Then
'Loop through the rows of the DataReader'
Do While sqlDataReader.Read()
'Do something here with the value in Column3'
myObj.myIntegerProperty= CInt(IIf(IsDBNull(.Item("Column3")), 0, .Item("Column3")))
Loop
End If

How to do Sql Server CE table update from another table

I have this sql:
UPDATE JOBMAKE SET WIP_STATUS='10sched1'
WHERE JBT_TYPE IN (SELECT JBT_TYPE FROM JOBVISIT WHERE JVST_ID = 21)
AND JOB_NUMBER IN (SELECT JOB_NUMBER FROM JOBVISIT WHERE JVST_ID = 21)
It works until I turn it into a parameterised query:
UPDATE JOBMAKE SET WIP_STATUS='10sched1'
WHERE JBT_TYPE IN (SELECT JBT_TYPE FROM JOBVISIT WHERE JVST_ID = #jvst_id)
AND JOB_NUMBER IN (SELECT JOB_NUMBER FROM JOBVISIT WHERE JVST_ID = #jvst_id)
Duplicated parameter names are not allowed. [ Parameter name = #jvst_id ]
I tried this (which i think would work in SQL SERVER 2005 - although I haven't tried it):
UPDATE JOBMAKE
SET WIP_STATUS='10sched1'
FROM JOBMAKE JM,JOBVISIT JV
WHERE JM.JOB_NUMBER = JV.JOB_NUMBER
AND JM.JBT_TYPE = JV.JBT_TYPE
AND JV.JVST_ID = 21
There was an error parsing the query. [ Token line number = 3,Token line offset = 1,Token in error = FROM ]
So, I can write dynamic sql instead of using parameters, or I can pass in 2 parameters with the same value, but does someone know how to do this a better way?
Colin
Your second attempt doesn't work because, based on the Books On-Line entry for UPDATE, SQL CE does't allow a FROM clause in an update statement.
I don't have SQL Compact Edition to test it on, but this might work:
UPDATE JOBMAKE
SET WIP_STATUS = '10sched1'
WHERE EXISTS (SELECT 1
FROM JOBVISIT AS JV
WHERE JV.JBT_TYPE = JOBMAKE.JBT_TYPE
AND JV.JOB_NUMBER = JOBMAKE.JOB_NUMBER
AND JV.JVST_ID = #jvst_id
)
It may be that you can alias JOBMAKE as JM to make the query slightly shorter.
EDIT
I'm not 100% sure of the limitations of SQL CE as they relate to the question raised in the comments (how to update a value in JOBMAKE using a value from JOBVISIT). Attempting to refer to the contents of the EXISTS clause in the outer query is unsupported in any SQL dialect I've come across, but there is another method you can try. This is untested but may work, since it looks like SQL CE supports correlated subqueries:
UPDATE JOBMAKE
SET WIP_STATUS = (SELECT JV.RES_CODE
FROM JOBVISIT AS JV
WHERE JV.JBT_TYPE = JOBMAKE.JBT_TYPE
AND JV.JOB_NUMBER = JOBMAKE.JOB_NUMBER
AND JV.JVST_ID = 20
)
There is a limitation, however. This query will fail if more than one row in JOBVISIT is retuned for each row in JOBMAKE.
If this doesn't work (or you cannot straightforwardly limit the inner query to a single row per outer row), it would be possible to carry out a row-by-row update using a cursor.

how to insert record set value in to the table?

Am having 6 fields in the record set
I want to insert into the table? How can I insert.
Used Query
INSERT INTO table values (recordset (0), recordset (1) ….. recordset (6))
But It showing Undefined function “recordset”
Please how to insert record set value in to the table?
Dim cmdCommand As New ADODB.Command
If recordSet.EOF = False Then
recordSet.MoveFirst
cmdCommand.CommandText = "insert into table ( field1) values ( " + recordSet.Fields(0) + ")"
cmdCommand.Execute()
recordSet.MoveNext
Loop Until recordSet.EOF = True
Keep in mind that you will need quotes in varchar fields
Konstantinos gives a good answer, but you just need to be careful of the potential for SQL Injection issues.
The simplest fix would be to just replace any single apostrophes with two.
.CommandText = "insert into table (field1) values ( '" & Replace(recordSet.Fields(0), "'", "''") & "')"
It sounds like you're attempting to INSERT multiple records using a single statement (one INSERT for 6 records instead of 6 INSERT for 1 record each). If that's the case, the INSERT syntax fully supports it.
Here's an example:
INSERT INTO MyTable
(row1, row2)
SELECT
value1, value2
FROM
OtherTable
When you look at it like this, you can basically take any SELECT statement and put the INSERT clause on top of it. Of course, the column names need to line up correctly for it to work.
You may insert data into database using the codeigniter Framework.
Database
Table Name : user
Fields Name : name , email
Insert a record using codeigniter:
//storing data **record** into an **Array**
$data(
'name' => 'Rudra',
'email' => 'rud.test#gmail.com',
)
//Inserting Array into Database Table Name : **user**
$this->db->insert('user',$data);
Try with the recordsetname.fields("field_name") and check that the recorsetname variable was defined. You can also use the syntax recordsetname!field_name.

Resources