I have table _house with field 'soft_delete' default is 0.
Then I have a View to check undeleted entries, hence I have
CREATE VIEW house AS
SELECT * FROM _house where soft_delete = 0;
But the problem now is that everytime I modify table _house, I'll need to re-update my view so that is not broken.
So each time after modify table _house, I execute
ALTER VIEW house AS
SELECT * FROM _house where soft_delete = 0;
I wanted to find an easier way to execute above alter script, so I tried to create a procedure/function with 'alter view' inside, but mysql seems to prohibit me doing that.
Question :
Any other solution to simplify this 'redundant' actions ?
The view definition is “frozen” at creation time, so changes to the underlying tables afterward do not affect the view definition. For example, if a view is defined as SELECT * on a table, new columns added to the table later do not become part of the view.
SOURCE
Related
I need to allow edits made via a DB GUI though to my auditing system so that they are also being tracked. I am updating the audit table using a BEFORE trigger, and i would like to be able to alter the audit row to indicate what the source of the update was (via an existing 'modified_by' column).
I cannot add an additional column to the audit table for this because I want to be able to copy from the updated table to the audit table without specifying table columns like below (I don't want this trigger to require that I update it with changes to the schema).
MY TRIGGER:
BEGIN
INSERT INTO contacts_audit SELECT * FROM contacts WHERE id = NEW.id;
END
PSEUDO TRIGGER:
BEGIN
IF(GUI EDIT) THEN
SET NEW.modified_by_id = 1; /* 1 is the administrator id */
END IF;
INSERT INTO contacts_audit SELECT * FROM contacts WHERE id = NEW.id;
END
A "DB GUI" connecting to the database is a client, a php connection is a client too, the same as any other way to connect to the database, so there is no flag like "this is php".
You can however use the USER() or SESSION_USER()-function in the trigger to get the active user/hostname of the current connection, so just use a different user/host for php and the gui if you want to seperate them.
I am using PHP MyAdmin Version 4.1.12.
I am trying to create a simple trigger that, after an update, sets 'dateModified' in table 'person' to CURRENT_TIMESTAMP. dateModified is of type TIMESTAMP. The way in which the update occurs to person is the setting of a single attribute in a single record through a X-Editable enabled grid view on a web page. After performing validation against the model with the updated attribute, a new database command is created with the relevant update SQL and executed. So each update only ever modifies a single row within 'person'.
Here is the SQL I wrote to create the trigger:
DELIMITER |
CREATE TRIGGER PERSON_AUPD AFTER UPDATE ON person
FOR EACH ROW BEGIN
SET #dateModified = CURRENT_TIMESTAMP ;
END;
|
DELIMITER ;
After performing updates, I see that the trigger hasn't fired, and the timestamp remains unchanged from the one they were created with (the default for dateModified, and dateCreated, are both CURRENT_TIMESTAMP, so they get set automatically on insert).
I have looked around for answers, and even looked into alternate methods to getting the update (the alternate method was calling a model's afterupdate method and performing separate SQL there on dateModified). I would prefer to exhaust every opportunity to use the triggers, before I go putting more code into my model.
Any help would be greatly appreciated.
Thanks to #juergend, the solution was the following:
Set trigger type to before update because after update cannot update attributes, and are best used to insert new records in related audit tables, etc.
Add NEW. to the front of the attribute you wish to modify.
I have a database setup and populated with some dummy entries and need the option to move it to recycle but not remove it. I'm starting to use relational databases and wondering the best way to do this.
Should I set a boolean field 'recycle' and query based on that or should I actually move those entries into a different table? I'm not sure how either one of these options compare to each other for performance.
Create new new column named deleted. Set it for deletion. Add it to all your WHERE clauses:
SELECT * FROM table WHERE deleted = false
DON'T archive your rows by moving them to another table. I did that when I was a kid and a novice database designer. That's a major headache and in this day and age it won't save you anything on query time. You exponentially increase the risk of losing data by moving rows like that. I like to look at Propel behaviors for how to implement these. Do it this way (read this issue in regard to the deprecation warning, and ignore the warning because it is incorrect: https://github.com/propelorm/Propel/issues/810):
http://propelorm.org/Propel/behaviors/soft-delete.html
Not this way:
http://propelorm.org/Propel/behaviors/archivable.html
If you had about 1,000,000 rows in a table, then I would suggest archiving them.
It depends on how often you'll need to read and create those rows, and how many there will be.
If you use the "recycle field" feature you will have to modify all queries (of course you can try renaming the original table as table_full, and create a VIEW of the table having only recycle set to false, but I'm not sure it will work in all foreseeable circumstances):
ALTER TABLE rows ADD COLUMN recycle BOOLEAN NOT NULL DEFAULT false;
ALTER TABLE rows RENAME TO rows_real;
SET #sql = CONCAT('CREATE VIEW rows AS SELECT ', (SELECT
REPLACE(GROUP_CONCAT(COLUMN_NAME), ',recycle ', ' ')
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'rows_real' AND TABLE_SCHEMA = 'test_db'),
' FROM rows_real WHERE recycle = false');
PREPARE stmt FROM #sql;
EXECUTE stmt;
Now INSERT, SELECT and DELETEs with primary key work as before, so those queries need no change.
Doing it the other way you will have to worry about locking the tables during the move, and wrapping everything into transactions.
To begin, I'd favor the "one table" approach, since it looks "cleaner" to me. With proper indexing, performances shouldn't be a problem.
You can create the column (boolean type) called e.g. hidden, and filter results like that:
SELECT * FROM table WHERE hidden = FALSE AND [your text]
You can also copy the row to another table and then remove it from the old one. I prefer that first option.
You've actually already answered this yourself. If you just want a hidden effect, then I too would use a TINYINT (or a boolean ofc, whatever your preference is!) field called hidden (imagine that!) and just set it as and when needed, then when pulling data from it. You'd just make sure you were only selecting the rows where hidden=0
:)
I want to put a form on my website to let users add events to their private calendar. For that, I would like to create a new column in MySQL each time the user add an event (always with the same form, one column for each event title, for example...)
Is it possible?
It is possible using ALTER TABLE
However, would it not be better to have a table called 'events' that holds all of them, with a column called 'userid' which contains the ID of the user the event belongs to.
Then you would know that every event exists in that table, and to get a users events you simply query that one table for rows that contain the users ID in the userid column.
Yes, but it's a very very very bad idea.
Add a table userevents, add a record to that. To get the output you want, have look for how to do pivot queries in mysql.
For this type of app. You can use magic websql (client side database)!
Web SQL Database is a web page API for storing data in databases that can queried using a variant of SQL.
More: http://html5doctor.com/introducing-web-sql-databases/
How to create a VIEW that it does not update data in a TABLE? For example, I want to delete rows only in the VIEW and the TABLE, on which the established VIEW, that there should be no deletions ... how to do it?
like this does not work ...
"CREATE OR REPLACE VIEW $prefix"
. "Test_View AS SELECT * FROM Table1 WITH LOCAL CHECK OPTION";
it is rather to check ... please, help!
If you want to have a VIEW where you can't update/delete data, add a distinct (e.g. on a unique key, where it essentially doesn't have an effect).
See the MySQL Ref on updatable views:
There are also certain other constructs that make a view nonupdatable. To be more specific, a view is not updatable if it contains any of the following:
Aggregate functions (SUM(), MIN(), MAX(), COUNT(), and so forth)
DISTINCT
GROUP BY
...
Deleting Rows from a view will delete them from the corresponding table.
You really should alter your view definition to exclude the rows you do not want.
You don't want to be using a view for this. You would need a second table that is updated by a on insert / on update trigger, if you want the table to exist permanently. Otherwise just create a temporary table for each query by using INSERT..SELECT statements.