Try to open new tables, but recieving error [duplicate] - mysql

My friend wants to create a new table in the database (his using vb.net, mysql). The tricky thing is that he wants to name the new table from the input being encoded into a textbox.
Is that possible? To create and name a new table from the input in the textbox.

#njm
you can create one string variable having query of "Create table <name>(field1,field2....)"
In above query must be replace with your input text box.
And pass this string to mysql command variable having its own connection ...
And simply execute this query...

This code should work....
Add one button to the form for testing purpose and place the following code to its click event
Imports MySql.Data.MySqlClient
'place this in the class.............
Dim myConnectionString = My.Settings.MySQL_DBConnectionString
Dim con As New MySqlConnection(myConnectionString)
'Code on the button...........
Dim createSql As String
Try
con = New MySqlConnection(myConnectionString)
con.Open()
Dim tblname = "anyInputName"
createSql = "CREATE TABLE " & tblname & " (id INT(6) NOT NULL AUTO_INCREMENT,otherField TEXT NOT NULL,PRIMARY KEY (id));"
Dim cmd As New MySqlCommand(createSql, con)
cmd.ExecuteNonQuery()
cmd.Dispose()
Catch ex As Exception
MsgBox(ex.Message)
Finally
con.Close()
End Try
Now go experimenting.......

Certainly it can be done.
Basically you build a string witha Create Table statement in it and then execute it.
e.g.
someSql "Create Table " + EditBox1.Text + "(.....)"
BUT
Building sql from user input opens you to sql injection attacks.
Legal identifiers, certain characters can't be used, some must be escaped, the name may already be in use...
Once you have the table, how is the code going to use it, to know that there is a table called "MyTable" in the database, why it's there...
You wouldn't normally just hand out create table permissions.
What about dependencies (relations, stored procs, contraints etc)
There are several ways of dealing with this, one is to do table creation in another app, build up rules and store meta information somehow that the code can use to use the table.
Another for simpler apps, is to give the table some unique name in the db and then use the the name entered by the user as an alias for it, so Show("MyTable") gets mapped to Show("UserTable1876")
Another possibility is if the table has definite common structure and it's just user Fred's copy of it is to add another column to the table and then simply add Fred's UserID when any CRUD functions are used.
So yes it can be done, should it? Depends....

Related

Displaying data from a mysql server on a datagridview object. is not displaying anything

I have tried making a dataset using the dataset tool to link it on the design side however that hasn't worked as it keeps disappearing and this is the other way it does not display any values on the datagrid view i am unsure why and i am fairly new to this side of vb so if you could explain it as well that would be great. Thanks in advance.
Imports MySql.Data.MySqlClient
Public Class Search
Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Try
If TextBox1.Text = "" Then 'this acts as a simple presence check on the textbox
Else
Dim val = "name"
If RadioButton1.Checked = True Then 'This changes the type of search i do as it filters which column the query looks in
val = "type"
End If
Await getDataSet(TextBox1.Text) ' waits for infomation to be retrieved
End If
Catch ex As System.Exception
System.Windows.Forms.MessageBox.Show(ex.Message) 'Catches any errors
End Try
End Sub
Async Function getDataSet(partname As String) As Task(Of DataSet) 'This retrieves the values that matches the users input
Return Await Task.Factory.StartNew(
Function()
Dim connectionString = "server=localhost; userid=root; password=; database=partstest1; CharSet=utf8;" 'These are the login details for the database in the form of a connection string
Dim commandText = "SELECT ID, Benchpoint, Name, Type, BrandID FROM `parts` WHERE `name` Like '%" & TextBox1.Text & "%';"
Using connDB = New MySqlConnection(connectionString), objCmd = New MySqlCommand(), objAdpt = New MySqlDataAdapter()
connDB.Open()
objCmd.Connection = connDB
objCmd.CommandText = commandText
objCmd.CommandType = CommandType.Text 'These lines specify the command i am using and execute it
objAdpt.SelectCommand = objCmd
Dim objDs = New DataSet()
objAdpt.Fill(objDs) 'Puts all of the values into a dataset
PartsDataGridView.DataSource = objDs.Tables(0) 'This shows the datasource and displays it
Console.WriteLine(objDs)
Return objDs
End Using
End Function)
End Function
End Class
Install MySQL/connector/etc
Install MySQL for Visual Studio (needed to get it to show as a datasource in VS) - https://dev.mysql.com/downloads/windows/visualstudio/
Add a new dataset to your project
Double click the dataset, right click the surface of it, choose Add >> TableAdapter
Choose existing connection or New Connection if you have no existing. Choose MySQL Database (install MySQL for Visual Studio from step 2 if this is absent)
Enter server details, choose to save the password, back in the wizard choose Yes, include sensitive.. and click Next, choose Yes, save the connection string, click Next, choose Use SQL Statements, Next, enter a suitable query that selects based on the primary key such as SELECT * FROM yourtable WHERE id = #id, Next, call the methods FillById and GetDataById to distinct them from other queries you may add later like FillByCity or GetDataByStatus. At the end of this wizard you should have a datatable and tableadapter that looks like your database table:
Switch to the form designer, and also ensure that the Data Sources window is visible (click View Menu >> Other Windows >> *Data Sources**), expand all the nodes in the Data Sources panel
Drag the node representing your table (mine is called person) out of the datasources window and drop it on the form. Several things will appear:
a datagridview already bound to the dataset's datatable showing person data,
a toolstrip with a textbox for inputting the ID (remember you made a query that takes a parameter),
another toolstrip with navigators and a save button),
a dataset (needed to store the data),
a bindingsource (acts as a link between the dataset's datatable and the grid, knows what current record is showing, allows sorting and filtering),
a tableadapter (an enhanced data adapter that will pull data from the db into the dataset and send back any changes),
a tableadapter manager (a device that knows what order to run updates in for hierarchical data)
Also, as a demonstration of how it works, drag all the nodes UNDERNEATH person onto the form also - you can see they have different icons. They will re-use most of the components on the form but you'll get textboxes, datetimepickers, checkboxes etc that are bound to the bindingsource and will hence show the current item from the underlying list (the datagridview shows them all, with an indicator of which row is current)
Run the project, type an ID into the textbox, hit **FillById*, write some new info into another row at the bottom - it will commit to the underlying dataset/datatable when you change row in the DGV, note that flicking back and forth between the rows in the DGV causes the textboxes to change as the notion of Current row is updated (navigating the grid, or clicking the arrows in the navigator changes the bindingsource .Current property, and all controls bind through the bindingsource
hit save - now go look in your db in MySQL Workbench - the new record is there. You've made a full databound UI, and not written a line of code - all the code is there in the FormX.vb if you want to see it - written for you by the designer. Take a look
Note that it still says -4 (in my UI) for the temp id; the program didn't download the new ID that was assigned by the DB. To make it do this, youre supposed to be able to go back to your dataset, right click the tableadapter, click Advanced Options, and tick on Refresh the datatable - this will cause the adapter to update any local IDs after it saves the row. IDs can cascade update if they are part of a datarelation between two datetables. In MySQL this doesn't work (I'm reporting a bug to them now), but you can make it work by manually editing the XML file representing the dataset (right click the DataSet in solution explorer, choose Open With.. Choose XML Editor, locate the insert statement eg:
INSERT INTO `person` (`Name`, `Birthdate`, `Salary`) VALUES (#p1, #p2, #p3)
Add another statement after it so it looks like:
INSERT INTO `person` (`Name`, `Birthdate`, `Salary`) VALUES (#p1, #p2, #p3)
;SELECT `Id`, `Name`, `Birthdate`, `Salary` FROM `person` WHERE `Id` = last_insert_id()
Now, saving the table will cause the UI to refresh with the ID values calculated by the auto increment in the DB

How to Prefill form from another DB based on the field value

I'm trying to create a solution to fetch data for a new record of SmallDB from secondary BigDB.
I created a linked table of BigDB to have it on SmallDB, so later I could use OnClick event of Button and it would be easier to reach that data.
Situation: I search form for the PersonID, but get negative result (this particular PersonID doesn't exist).
Then, in the form I create new record and enter this new Person ID in the PersonID field.
My plan is to be able to click FetchData button and pre-fill Name, Last Name and other details to the form from BigDB for this particular PersonID.
Then I would save the record with save button.
It looks to me, that solution could be similar to: https://stackoverflow.com/a/53180365
But I don't know how to ensure that I would get data from BigDB only for that particular PersonID that I entered into Form field.
Or perhaps in my situation another method would work better?
Thank you!
Following example code from link referenced in question, apply filter criteria to query object via PARAMETERS. However, unless you have query object set up with PARAMETERS clause, I don't see need for QueryDefs and instead of referencing query object, can use SQL statement in code.
Assuming PersonID is a text type field:
Dim db as Database
Dim rs As Recordset
Set db = CurrentDb
Set rs = db.OpenRecordset("SELECT * FROM tablename WHERE PersonID='" & Me.tbxPID & "'")
If Not (rs.EOF And rs.BOF) Then
If you are not on new record row of form, either first move to it manually or with code, or use another approach. An INSERT SELECT action SQL can create a new record in SmallDB with data from BigDB.

Updating an Access Table with a CSV File Automatically

Problem Background:
I have a Powershell script that I can execute from my Microsoft Access Form that scans through file folders that contain information on different facilities, and produces a CSV that looks something like:
SiteCode FacilityNumber DocumentType HyperlinkPath
DKFZ 10 DD1400 C:\FACILITIES DATABASE\path
DKFZ 10 FLRPLN C:\FACILITIES DATABASE\path
SMQL 17 P1 C:\FACILITIES DATABASE\path
SMQL 17 P2 C:\FACILITIES DATABASE\path
So that way every time new files are added to those folders, I can just run this script and produce an updated list of everything I have:
C:\...\Output\scanResults.csv
All I need now is to take that CSV file and update (or even overwrite) a Table that I have in an Access database, which has relationships to other tables and is used by various Queries and Forms in the database. The CSV columns are already named and formatted in the same way as the Access Table.
I've looked at and tried to replicate the following threads:
VBA procedure to import csv file into access
Access Data Project Importing CSV File In VBA
VBA Import CSV file
The closest answer I found is:
Sub Import()
Dim conn as new ADODB.Connection
Dim rs as new ADODB.Recordset
Dim f as ADODB.field
conn.Open "DRIVER={Microsoft Text Driver (*.txt; *.csv)};DBQ=c:\temp;"
rs.Open "SELECT * FROM [test.txt]", conn, adOpenStatic, adLockReadOnly, adCmdText
While Not rs.EOF
For Each f In rs.Fields
Debug.Print f.name & "=" & f.Value
Next
Wend
End Sub
But this obviously won't write the data into the table, and I could not understand what the author was trying to say with respect to changing Select to Insert.
I've also found:
DoCmd.TransferText acImportDelim, "YourCustomSpecificationName", _
"tblImport", "C:\SomeFolder\DataFile.csv", False
Since both of these are from 2010, I wonder if there isn't a better way to accomplish this in Access 2013. And while I can do this all manually, I would like to incorporate it into the VBA code I use to tell Powershell to produce the CSV, that way I can make it and then upload it immediately.
Any help or suggestions are greatly appreciated. I'm still very green to Access, VBA, and SQL statements in general, so this has been very much a "learning as I go" process.
I prefer to use SQL clauses and queries to import such data. The details depend on your exact configuration, but it tends to look something like this:
SELECT *
INTO MyTable
FROM [Text;FMT=CSVDelimited;HDR=No;DATABASE=C:\...\Output].[scanResults#csv]
Or append the information to the table instead:
INSERT INTO MyTable
(SiteCode, FacilityNumber, DocumentType, HyperlinkPath)
SELECT *
FROM [Text;FMT=CSVDelimited;HDR=No;DATABASE=C:\...\Output].[scanResults#csv]
This allows you to do checks before importing (using a WHERE clause), import only specific values, and allows you to customize a lot without using external files.
DATABASE= is followed by your folder name (use {} if there are characters that need escaping in there), and then followed by your file name with . replaced with #.
You can execute it by either saving it as a query, or using it as a string in either VBA or a macro. Note that I rarely recommend macro's, but you can execute them using a scheduled task and close Access after importing.
To backup and restore a relation before and after updating, you can use the following functions:
Public Function DeleteRelationsGiveBackup(strTablename As String) As Collection
Dim ReturnCollection As Collection
Set ReturnCollection = New Collection
Dim i As Integer
Dim o As Integer
Do While i <= (CurrentDb.Relations.Count - 1)
Select Case strTablename
Case Is = CurrentDb.Relations(i).Table
ReturnCollection.Add DuplicateRelation(CurrentDb.Relations(i))
o = o + 1
CurrentDb.Relations.Delete CurrentDb.Relations(i).NAME
Case Is = CurrentDb.Relations(i).ForeignTable
ReturnCollection.Add DuplicateRelation(CurrentDb.Relations(i))
o = o + 1
CurrentDb.Relations.Delete CurrentDb.Relations(i).NAME
Case Else
i = i + 1
End Select
Loop
Set DeleteRelationsGiveBackup = ReturnCollection
End Function
Public Sub RestoreRelationBackup(collRelationBackup As Collection)
Dim relBackup As Variant
If collRelationBackup.Count = 0 Then Exit Sub
For Each relBackup In collRelationBackup
CurrentDb.Relations.Append relBackup
Next relBackup
End Sub
Public Function DuplicateRelation(SourceRelation As Relation) As Relation
Set DuplicateRelation = CurrentDb.CreateRelation(SourceRelation.NAME, SourceRelation.Table, SourceRelation.ForeignTable)
DuplicateRelation.Attributes = SourceRelation.Attributes
Dim i As Integer
Dim fldLoop As Field
Do While i < SourceRelation.Fields.Count
Set fldLoop = DuplicateRelation.CreateField(SourceRelation.Fields(i).NAME)
fldLoop.ForeignName = SourceRelation.Fields(i).ForeignName
DuplicateRelation.Fields.Append fldLoop
i = i + 1
Loop
End Function
And then, when importing:
Dim colRelBackup As Collection
Set colRelBackup = DeleteRelationsGiveBackup("MyTable")
'Delete MyTable
'Import new version
RestoreRelationBackup colRelBackup
(Note that the code is quite long, developed for a project several years ago, and not extensively tested. If a field name/type is not exactly like how it was before the import, the restore of the backup might fail and the relations will be permanently lost).
So some high level architect advice: replacing data versus replacing table
It is easier replacing data - - the new incoming data must be the exact same structure as the existing table (i.e. same field names and no new fields).
just fire a Delete Query to the existing table that clears out all records
then fire an Append Query to the linked CSV file that writes all those records into the existing table
very simple really.
You can replace the tables if you must - and you are already down this path. You can delete those table relationships entirely. That table relationship feature is useful - but not mandatory. You can create relationships at the query level as an alternative. Essentially the table relationships just auto create the query level relationships. If you delete the table relationships then one must simply create the table relationships at the query level manually - they don't automatically appear. Note however that if one is relying on cascade deletes or referential integrity, then removing table relationships will undo that - so you should check these points.
Deleting Table Relationships will not break any existing queries. Their table relationship join lines will remain intact.

Preventing MSAccess linked tables from having a dbo_ prefix?

Is there a way to prevent MSAccess from concatenating 'dbo_' as the prefix to tables linked from a SQL Server db?
No. Microsoft Access' native naming convention process will force the name <schema>_<ObjectName> as your default table name. There are no controls or settings which will allow you to change that, except in code. It's rather complex and goes beyond the scope of this question, but if you do the linking in code (which I do) then you can store the TableAlias and create the linked table name that way.
You can write your table definition in the code to attach the table as below where
strTableAlias is your display name in Access
strTableName is your table name with schema <schema>.<ObjectName>.
Dim td As DAO.TableDef
set td = CurrentDb.CreateTableDef(strTableAlias, dbAttachSavePassword, _
strTableName, strConnectionStr)
CurrentDb.TableDefs.Append td
If you don't do the linking in code as mentioned by Johnny you can rename the links with this VBA code:
Public Sub Remove_DBO_Prefix()
Dim obj As AccessObject
Dim dbs As Object
Set dbs = Application.CurrentData
'Search for open AccessObject objects in AllTables collection.
For Each obj In dbs.AllTables
'If found, remove prefix
If Left(obj.Name, 4) = "dbo_" Then
DoCmd.Rename Mid(obj.Name, 5), acTable, obj.Name
End If
Next obj
End Sub
Courtesy https://www.microsoftaccessexpert.com/Microsoft-Access-Code-RemoveDBOPrefix.aspx
If you're doing this with the idea of using queries that you generate in Access outside of Access remember that Access creates it's own sql dialect so you may need to convert double quotes to single and # to ' among other things.

How to retrieve several rows from database

Okay, so I've made a new project which allows users to send messages to each other. I've almost got it finished, just a few things need to be cleared up.
I've successfully allowed the user to send the message (via mysql). Now Im at the part where Im supposed to retrieve the message and display it in the form; this is where Im stuck. It'd be easy to do if the user has only 1 message in the database, but what if he had more than 1? How would I retrieve them all and display them in the form. Im using this query:
SELECT ToID
FROM Message
WHERE (ID LIKE #ID)
What it does is check the database for any messages containing the recipient as the user's ID. If the database does in fact contain any message, then the program will display them in the textboxes. But in the case if more than 1 message, how would the database display them in the form? The form has textboxes for:
Sender
Subject
Date.
This is the query I hoped to use for retrieving the message:
SELECT ID, Title, Body, Date, FromUsername
FROM Message
WHERE (ID LIKE #ID)
Please help? Any other solutions are fine as long as its easy to understand(im new to vb).
If I understand you correctly, why not use a list box instead of a textbox to display the messages. That way it doesn't matter how many messages there are, they will just keep getting added to listbox.
Something like:
For Each s as String in messageList
listbox1.items.add(s)
Next
Edit:
Retrieve the data and then bind it to the listbox - I've never really worked with mysql so I've lifted the code from a google search - it should get you started though.
dim table as new DataTable("table1")
' Create a Connection
using conn as new MysqlConnection("...connectionstring")
conn.Open() ' Open it
' Create a new Command Object
using cmd as new MysqlCommand("SELECT ID, Title, Body, Date, FromUsername FROM Message WHERE (ID LIKE #ID)", conn)
' Create a DataAdapter
' A DataAdapter can fill a DataSet or DataTable
' and if you use it with a CommandBuilder it also
' can persist the changes back to the DB with da.Update(...)
using da as new MysqlDataAdapter(cmd)
da.Fill(table) ' Fill the table
end using
end using
end using
' A Binding Source allows record navigation
dim bs as new BindingSource(table, nothing)
' You can bind virtually every property (most common are "text" "checked" or "visible"
' of a windows.forms control to a DataSource
' like a DataTable or even plain objects
ListBox1.DisplayMember = "Message"
ListBox1.ValueMember = "ID"
ListBox1.DataSource = table2