SQL - Recursive delete in one query? - mysql

Assuming I have a DB like this:
Folders (with "parent folder" column)
Files (with "folder" column)
Is there a way to delete all files in a folder that has sub folders in only one query?
Example:
Folders:
id,name,parent
1, folder1, 0
2, folder2, 1
3, folder3, 2
Files:
name, folder
file1, 2
And I try to delete folder1. That single query should delete all files in folder2, and folder3 becasue folder2 is under folder1, and folder2 is under folder1.
** I know I can do this as a recursive script, but I want to educate myself more

As suggested by #jarlh, a really nice solution is having a Foreign key, with on delete cascade.

Related

MySQL Structure for tree with different types

I've been tasked with building a tree structure. I'm inexperienced with this thing and was wondering if there's any glaringly obvious issues with my approach.
So I have a large table of files (and fields regarding regularly use data in that file) which must remain the same, and I'm creating a structure where there's folders, so folders can contain X number of files and X number of folders. But the files can have no children.
With the structure I was thinking I'd have to handle either a null folderId or fileId but other than that I think its okay.
Desired output is that the tree structure is to be lazy loaded over a REST API, so a user can click a node and Ill retrieve all its children using an ID. I'm not sure my design is ideal so I'm after some feedback.
I was going to build my table structure like so (sorry in advance for bad formatting):
FileTable
Id
Version
File
FolderTable
Id
Name
ItemTable
Id
FolderId foreignKey
FileId foreignKey
TreeTable
Id
ParentId TreeTable Foreign Key
Item ID Foreign Key
I'm thinking of using just one table
DirObject
with the following fields:
Id
ParentId #Link to parent object -- parent should be of type 'Folder'
ObjectType #Folder or File
Version
OwnerUser
OwnerGroup
Permissions
LastUpdate
FileSize
Status
Path
Update:
Since you will be needing a separate table for the files, try this:
Folders
Id
ParentId #Link to parent folder
OwnerUser
OwnerGroup
Permissions
LastUpdate
Status
Path
Files
Id
FolderId #Foreign key from Folders table
OwnerUser
OwnerGroup
Permissions
LastUpdate
Status
Path
Note:
Value of Path should just be like how normal directories work
\folder1\folder2\folder3\filename
This will help when you want to get the size of a certain folder.
your query will look like
SELECT SUM(FileSize) from db.files where path like '\path\of\folder\%';

SSIS Package copy/move based on condition. check archive folder before move/copy to process

I'm working on a Ssis package and would like to know, how I can achieve the following:
I want to move files from a drop folder into a process folder and I want to implement the following rule:
If file does not exist in archive move file to process and archive.
If file exists in archive drop file (don't archive and don't move to process).
The test "if" exists must be based on file name and time stamp (when raw file got created).
Any ideas?
You can do this by simple way which I have done this in few days back.
1) Create a variable FileName(string), FileExists(boolean)
2) Drag the File System Task and based on your condition you can Copy/Move/Delete file or folder.
3) In my case based on the time frame I archive the file which is move the file from one folder to another by adding one more variable name DestinationFolder (string).
4) The condition I applied is in Precedence Constraint (right click on properties or double click Precedence constraint editor then expression and constraint and give the expression as #fileexists == TRUE or FALSE).
This should work just fine.

Updating multiple fields when changing one word in string?

Usually I would post code, but this time I have no true idea of where to start or I might just be over complicating a simple issue.
QUESTION
So I have a table that stores URL paths as strings
(Example: 192.168.x.x\Location\Location2\SPECIALNAME\Folder\Folder2)
and this is allowing us to build a folder/file repository on the client end for our users to add files and access files.
My question is how I would go about updating all fields associated with those that match
"\SPECIALNAME\" and replace 'SPECIALNAME' with another value (if the person changes the name of the main folder, then all subfolders and things linked to this folder should be updated with the new name)
To try and make this more clear of a question:
If my locations are stored in my table:
URL\ **SPECIALNAME** \FOLDER\SUBFOLDER
URL\ **SPECIALNAME** \FOLDER\SUBFOLDER\SUBSUBFOLDER1
URL\ **SPECIALNAME** \FOLDER\SUBFOLDER2
URL\ **SPECIALNAME** \FOLDER\SUBFOLDER2\SUBSUBFOLDER1\SUBSUBFOLDER2
URL\ **SPECIALNAME** \FOLDER\OTHERFOLDER
I want to specifically update the field where SPECIALNAME is with the new name that the user might change it to.
This update statement will probably be doing batches of 80+ updates upon a single name change to give a perspective of how many URL paths will be updated with the new name
UPDATE table SET url = REPLACE(url, '\\SPECIALNAME\\', '\\MORESPECIALNAME\\') WHERE url LIKE '%\\SPECIALNAME\\%';
To start with the query:
SELECT *
FROM tablename
WHERE path LIKE "%SPECIALNAME%"
Then you can loop through the results and
$newPath = STR_replace("SPECIALNAME", "NEWNAME", $query['path']);

Count of related items in a 2nd table with zero results needed (query check please)

This MySQL statement is a bit over my head. I pieced it togather through a lot of Google searches. It seems to work right but I just wanted to see if I could get a thumbs up. I'm paranoid I did something a bit off and some issue could come up I'm not understanding.
I have a 'directories' table, 'folders' table and 'documents' table. (directories have many folders, folders have many documents).
On a web page, I have a select where a user can choose a directory (which has many folders). This query is for an AJAX call that loads a second select with the list of all folders belonging to the directory (getting the id's and names to load the 'folders' select).
So, this query will be made against one directory to get a list of folder id's and folder names for that directory. I also needed the folder name to contain a count of how many documents are contained in each folder. Also, I originally had just "join" which did not return zero results but changing it to "left join" listed folders with 0 documents (don't have an understanding of the different types of joins yet).
MY FRANKEN-QUERY:
SELECT f.id, CONCAT(f.folder_name , ' (', COUNT(DISTINCT d.id), ' documents')') AS folder_name
FROM folders f
LEFT JOIN documents d ON d.folder_id = f.id
WHERE f.directory_id = '2'
GROUP BY f.id
ORDER BY f.folder_name
RESULTS (seems to work fine):
id folder_name
1 MAIN (2 documents)
8 test1 (2 documents)
9 test2 (3 documents)
50 test3 (0 documents)
Thanks - much appreciated!
It looks fine offhand, but just run a couple tests on your data ans make sure you get consistent (correct) results.
Assuming document.id is a primary key, you can remove the DISTINCT keyword from the count.
For more on the various join types
http://en.wikipedia.org/wiki/Join_%28SQL%29

Naming conventions for template objects

We have a set of template files which can be copied by users and modified later. We have a unique constraint on the "name" field, so when some user copies a template file say "File 1" we add it as "Copy of File 1" and if he copies a template file say "File 2" we add it as "Copy of File 2" (i.e. we add an appropriate prefix, when we copy these files) so we don't violate the unique constraint.
But if he adds the same file "File 1" again we run into a unique constraint violation error, what kind of naming convention should I follow, so that I can make it intuitive enough for the end user.
You could add the date of when the copy was made to the filename. Adjust the precision to the time frame least likely to cause a problem.
e.g. File1 -> File 1 - Copy 2010-12-29 0017
Also, I prefer suffixes to prefixes for copies so that the copy is stored next to the original.
Do the something similar what the explorer of win7 does when you drag-and-drop-copy a file within the same folder:
index.html
index - Copy.html
index - Copy (2).html
index - Copy (3).html