On my website I use simple file management. User can upload files, see the list and delete them. In database I have one table Files which contain information about files (file name, description, insert date).
I display all the files in GridView control with SQLDataSource.
DeleteCommand="DELETE FROM Files WHERE id = #id"
What I want to do is to delete the asocciated file when user deletes row from table. I was trying to do this in OnDeleting event but it seams that I have to execute another SELECT to get file name. Is it the only way to do this? Or is it any other better way? Or how to get the file name from inside the OnDeleting event?
EDITED: Databse is SQL Server, but it is not important in this case. I store files in file system. In database there are only names of files.
Rather than deleting your row directly, create a stored procedure called something like deleteFile(#ID int). Inside this proc, get the filename:
Select FileName From Files Where ID = #ID
Then Delete the file suing whatever method you're using to delete actual files.
Then delete the row
Delete Files Where ID = #ID
If you try this from the GridView.RowDeleting event, you can use the passed-in parameter GridViewDeleteEventArgs to get the row about to be deleted. Assuming the name is in this row, you can then use it to delete the file.
I know they can be evil, but this seems like a place where triggers could be used, that way if the delete query is run from multiple places the file would still be deleted.
if it is MS SQL
DECLARE #Command varchar(8000)
SELECT #Command = 'del c:\' + DocID FROM Deleted
xp_cmdshell #Command
You need some way to cross reference the table entry with the file - presumably they both have a unique file name? If so, you could use that to delete the file from the same place in your code-behind that you are issuing the DB delete command.
Lukasz,
If you are using a Gridview to bind the data, you can define the DataKeyNames attribute and then in the RowDeleting event do the following:
string documentName = (string)GridName.DataKeys[e.RowIndex].Value;
DeleteDoc(documentName);
Related
In my Microsoft SQL Server Management if I use this query:
select * from Modules where ModuleTitle like '%MyOldString%'
I can find multiple results with different ModuleIDs like 1, 2, 5, 1257, etc.
So now, I want to backup this ModuleIDs, then change all the string "MyOldString" to "MyNewString" in all that Module Titles, how should I do ?
If change one of them, I can use:
update Modules set ModuleTitle = 'MyNewString' where ModuleID = 1257
But now, I only need to replace the string and all at one for all that in the search results, is it possible ? And I need to backup that ModuleIDs, in case I need to change them back.
You could update it with a replace query:
update Modules
SET ModuleTitle = REPLACE(ModuleTitle,'MyOldString','MyNewString')
WHERE ModuleTitle like '%MyOldString%'
;
First, you can easily change the string using the same WHERE expression as you do for searching.
select * from Modules where ModuleTitle like '%MyOldString%'
You can update using
update Modules set ModuleTitle = 'MyNewString'
where ModuleTitle like '%MyOldString%'
As far as backup, where do you want to back the records up to? Just title or the full record?
One option would be to write a trigger, and automatically back things up into a separate table (containing ID, old title, and an update date). The benefit of the trigger would be the records get logged every time the title changes, not just when your code does it.
CREATE TABLE Module_backup
(Module_ID int,
oldtitle VARCHAR(200),
updDate DATETIME DEFAULT getDate()
)
Add a trigger to the table. Basically, in the trigger, if both INSERTED and DELETED are populated (i.e. an update operation),
INSERT INTO Module_backup(Module_id,oldtitle)
SELECT Module_Id,ModuleTitle FROM DELETED
I use Navicat and this command to create temp table in sqlite:
create temp table search as select * from documents
Then when i try to query:
select * from search
I got:
no such table: temp.sqlite_master
or:
no such table
The table doesn't appear in table list too, but when I try to create it again I get:
table search already exists
What is the problem? is it from navicat?
You create statement looks correct to me. When you create a temp table it is deleted when you close the connection string used to create the table. Are you closing the connection after you create the table and then opening it again when you are sending the query?
If not, can you include your query statement too?
It's like a bug in SQLite DLL shipped with Navicat. Test it somewhere else worked ok.
Documentation of SQLite tells this about CREATE TABLE:
If a is specified, it must be either "main", "temp",
or the name of an attached database. In this case the new table is
created in the named database. If the "TEMP" or "TEMPORARY" keyword
occurs between the "CREATE" and "TABLE" then the new table is created
in the temp database. It is an error to specify both a
and the TEMP or TEMPORARY keyword, unless the is
"temp". If no database name is specified and the TEMP keyword is not
present then the table is created in the main database.
May be you should accesse table via temp prefix like this: temp.search.
I have an appcelerator titanium project (you don't need to be familiar with the platform to help me) that I am using to create an iOS app. I want to have a database with a table that is filled with several rows for the first time, and then left alone after the first time.
I know you can create a table if it doesn't exist. Is there something similar for Inserting data?
Thanks!
Expanding on MPelletier's response with some Titanium-specific code, you could do the following in your project:
var my_db = Ti.Database.open('nameofdb');
var my_result_set = my_db.execute('SELECT * FROM MyTable');
var records = my_result_set.rowCount;
The records variable will indicate whether or not you have data in your table and then you can act accordingly.
There are a couple of nice ORM-ish utilities out there for Titanium: TiStore and Joli are the two I've used. Both are inspired by ActiveRecord and can be helpful in reducing your DB-related code. They're on Github if you want to know more about them!
There's INSERT OR REPLACE if you want, but you might as well just check against the number of rows on the table:
SELECT COUNT(*) FROM MyTable;
Then decide to enter them on that.
You can create your DB and insert data in it via SQLLiteManager or whatever tool you want and then dump it.
Take the file you dumped, put it in your Titanium project folder (somewhere in the Resources folder).
Then this line of code will take the content of the .sqlite file and insert it in the iOS db:
var db = Ti.Database.install('../your-db.sqlite', 'your-db-name');
Just don't forget the CREATE IF NOT EXISTS statement in your SQL file.
Or use REPLACE instead of INSERT as MPelletier said.
I want a debug function to do this, but I'm unaware of whether one already exists. Going through and using 'drop table' for each of my tables will be a pain.
Help appreciated.
Since the database is just one file, you can indeed just erase it. If you want something more automatic, you can use the following to do it all programmatically:
Recover your schema:
SELECT group_concat(sql,';') FROM sqlite_master;
Disconnect from the database
Delete the database file
Create your schema again with what was returned from the above query
If you used any particular options for your original database (page_size, etc), they will have to be declared manually as well.
to "drop database" for sqlite, simply delete the database file (and recreate if needed)
I'm unable to retrieve the latest inserted id from my SQL Server 2000 db using a typed dataset in asp.NET
I have created a tableadapter and I ticked the "Refresh datatable" and "Generate Insert, Update and Delete statements". This auto-generates the Fill and GetData methods, and the Insert, Update, Select and Delete statements.
I have tried every possible solution in this thread
http://forums.asp.net/t/990365.aspx
but I'm still unsuccesfull, it always returns 1(=number of affected rows).
I do not want to create a seperate insert method as the auto-generated insertCommand perfectly suits my needs.
As suggested in the thread above, I have tried to update the InsertCommand SQL syntax to add SELECT SCOPY_IDENTITY() or something similar, I have tried to add a parameter of type ReturnValue, but all I get is the number of affected rows.
Does anyone has a different take on this?
Thanks in advance!
Stijn
I decided to give up, I can't afford to waste any more time on this.
I use the Insert statement after which I do a select MAX(id) query to hget the insert ID
If anyone should have a solution, I'll be glad to read it here
Thanks
Stijn
I successfully found a way to get the incremental id after insert using my table adapter.
My approach is a little different, I'm using a Store procedure to make the insert, so my insert command has all the values but the ID, I made the sp return the ID just calling:
SET #ID=SCOPE_IDENTITY()
and then
COMMIT TRAN
and last line will be
RETURN #ID
Then I searched my table adapter parameters for InsertCommand and set the #RETURNVALUE to the column of the incremental ID of the table, so when it's executed automatically put the return value on the id field.
Hope this help
You need to tell your table's table-adapter to refresh the
data-table after update/insert operation.
This is how you can do that.
Open the properties of TableAdapter -> Default Select Query -> Advnaced options. and Check the option of Refresh the data table. Save the adapter now. Now when you call update on table-adapter, the data-table will be updated [refreshed] after the update/insert operation and will reflect the latest values from database table. if the primary-key or any coloumn is set to auto-increment, the data-table will have those latest value post recent update.
Now you can Call the update as TableAdapterObj.Update(ds.dataTable);
Read latest values from the DataTable(ds.dataTable) coloumns and assign respective values into the child table before update/insert. This will work exactly the way you want.
alt text http://ruchitsurati.net/files/tds1.png