I'm just beginning developing with the Yii 2 Framework, and installed the officially advanced app .
The migration script of the user table defines '10' as the default value for the column 'status'.
'status' => $this->smallInteger()->notNull()->defaultValue(10),
I'm just wondering why they use this?
In the past I have used boolean (true/false) respectively 0/1 (stored as smallint or bit in mssql).
Take a look at contents of common\modules\User class. There are two constants for statuses:
const STATUS_DELETED = 0;
const STATUS_ACTIVE = 10;
The boolean type is not used because it assumes usage of multiple statuses (more than two), not limited to only deleted and active (in this case we can simply have boolean column is_active or something like that).
The 0 and 10 is used as kind of boundary values, to add other constants in between in the future. Also it's kind of extreme states, while other are intermediate.
The actual values of constants can vary, the more important thing is once it's declared and some data already exists, you can't simply change it to another value without data migration.
But if you are not satisfied with these values, you can change it to 0, 1 and add others as 2, 3 and so on.
You can also completely remove it and make column boolean and rename it to is_active as I said before.
Remember - it's only a template, you can change it to fit your needs.
Related
We need a table to store requests for a copy of a contract, let's say contract_copy_requests.
The user either made a request, or did not. The field is unlikely to ever toggle.
Which of these column options is "correct":
profile_id, request date (and only write ids that made a request in here) OR
profile_id, has_requested_copy, updated_date
The latter is more complete and extensible, but the former is simpler and doesn't require either a nullable field or backfilling existing data with false for everyone since they haven't made the choice yet.
Is there any real reason to do #2? Btw, this is more of a generic question - I have had this use case come up about 3 times in the past month and I always lean toward #1 but wanted to validate it.
The first option is better.
It is smaller, and you lose no functionality: for example, it will be easy to get the users that didn't make a request:
... WHERE NOT EXISTS (SELECT 1 FROM contract_copy_requests AS ccr
WHERE ccr.request.id = /* column from the outside */)
I have a table with guid identifier and one field that is a 5 characters string that can be specified by user, but it is optional, and it should be unique per user. I'm looking for a way to have this field always there, even if user doesn't specify it. The easiest approach is to have it like "00001", "00002"... etc. in case that user doesn't specify it, it is stored like this. I'm using SQL and entity framework core. What is the best way to achieve this?
EDIT: maybe trigger that will check after insert if that field is not specified and then just take current row number and convert it to string? does this make sense?
Cheers
Setting a default value to '00001' can be done define the field with:
NOT NULL DEFAULT right('0000' || to_char(SomeSequence.nextval),5) (pseudo-code to be adapted to the DBMS you are connected to).
Compared to the solution in your EDIT, this will at least guarantee that 2 inserts at the same time from 2 different users get assigned different values.
The real problem comes with the unique constraint on the column. This does not work nicely when mixing manual input with calculated values.
If as a user, I input (manually) 00005, then the insertion will fail when SomeSequence reaches 5.
I think this problem will exist regardless of how you implement the generation of values (sequence, trigger, external code, ...)
Even if you are fine with coding some additional (and probably complicated) logic to manage that, it will probably decrease concurrency.
In the context of my SAP Application I added a column to an existing table and would like to define a default value for it, so that old code working with the table (code that is inserting lines especially) doesn't have to care about the new column - rather I want it to be filled with a predefined default value automatically (only if no value is specified of course).
The DB-system that lies behind is an Oracle-DB, though I have only access to it through the SAP-GUI and the ABAP-SQL.
As our company expert for SAP did not know if this is possible I thought maybe someone here would. So - is this possible and if it is - how?
Edit - Requested Scenario details:
The scenario is actually very simple: We have a users-table for our application containing the standard user stuff (name, some setting, Ids, division, a bunch of flags and so on), and I added a column to store a simple setting (the design the user has chosen for his webinterface). It contains simply a name (char 40). That's the column I talked about above and I want the default value for it to be let's say "Default Design".
Please, don't even think about doing this on a database level. Seriously. Changes made to the database layer directly will not be visible inside the system and lead to all kinds of strange side effects that will be a nightmare to support. Besides, your changes won't be picked up by the Change and Transport System - you'd have to update the QA and Production systems manually.
If possible, I'd recommend to choose your domain values in a way that the neutral field value (spaces, zero, whatever) corresponds to your default value. If this is not possible, please describe your scenario in detail to get a more specific answer.
The SAP R/3 / ABAP environment does not give you the option of adding default values for a column. You can only choose to force the system to fill the non-NULL default values when adding a column, but this is usually a bad idea. It takes time to modify all the data and insert the default values, and depending on the table size and criticality, this can lead to a production outage. Filling the fields with default values has to be performed by the application server, not the database. In your case, I'd just add the logic in the read-access module, something like
IF my_user-ze_design IS INITIAL.
my_user-ze_design = co_ze_default_design.
ENDIF.
You can define default values for columns added to tables - and if your DB is Oracle 11g (or later), Oracle introduced "Dictionary Only Add Column", which means the default value metadata is stored only in the dictionary - so existing records do not need to be updated with the default value and there is no overhead, no matter how large the table.
Currently I have a database that stores boolean fields as VARCHAR(1) ('T' or 'F'). I want to replace these with BIT. The problem is that this would require a ton of changes in the program that uses the database. So I thought the logical step is to add a BIT field and replace the existing VARCHAR(1) field with a computed column that I access rather than accessing the BIT field (thus the program can continue to work as is without changes, and be changed to use the BIT field over time).
I know this won't work (UPDATE and INSERT doesn't work on computed columns). I know one option is to rename the existing table and add a view through which to access it, but I don't see that as a viable solution, as adding and removing columns, changing dependent views, etc. would be prone to errors (and it's not a neat solution in my opinion).
My question is - what are my options to achieve the above behaviour (such that the program can continue working as is)?
An example:
User (Active VARCHAR(1), ...)
Changed to use computed columns: (won't work)
User (Active_B BIT, Active AS CASE Active_B WHEN 1 THEN 'T' ELSE 'F' END, ...)
UPDATE: Fixed error in example.
It would have to be:
ALTER TABLE dbo.User
ADD Active AS CASE Active_B WHEN 1 THEN 'T' ELSE 'F' END PERSISTED
You need to use the column name (not the datatype) in the CASE. And I'd recommend making the computed column persisted, too - so that the value gets actually stored on disk (and not recomputed every time you access it).
An option is to have both a VARCHAR and a BIT field and use triggers to update between them.
I'll just have to figure out how to prevent infinite recursion (one idea is to have a field that serves no other purpose than to check if this trigger resulted from an update within another trigger (check if we're updating it and include it in the update in the trigger)). The updates need to go both ways to allow for easy backward compatibility.
The AdventureWorks Data Dictionary specifies that the [EmailPromotion] column in the [Contact] table is an int and that:
0 = Contact does not wish to receive e-mail promotions.
1 = Contact does wish to receive e-mail promotions.
and [Employee].[CurrentFlag] uses bit as follows:
0 = Inactive
1 = Active
My question has two parts:
Is there a good reason to use the int datatype in place bit (both uses will be documented)?
What naming conventions for boolean and boolean-like columns do you recommend? (e.g. IsActive, ActiveFlag, Active)
For the first part they are probably allowing for future status codes (although with that column name it is hard to imagine what that could be...).
You will find a lot of dissent on your second question, but I prefer IsActive as a name in this case. I find it reads well, and prevents double negatives in code that you would get if you used something like IsInactive.
Is there a good reason to use the int datatype in place bit (both uses will be documented)?
INT is consistently supported. While BIT is becoming more common, I'll wager the support is just a mask for an INT column with a CHECK constraint. There's a good asktom question about why Oracle doesn't have a specific BIT/BOOLEAN data type...
What naming conventions for boolean and boolean-like columns do you recommend? (e.g. IsActive, ActiveFlag, Active)
Same as programming, they should be prefixed with "is" and when read, should present a yes/no question to infer the column is a boolean indicator. So "isActive" would be my decision, but I would be probing to see if the situation didn't require a STATUS table & foreign key.
Whatever floats your boat. The only important thing is naming convention and consistency across the database.
Using int for a flag isn't justified, I would've used tinyint, I hardly ever use bit at all, because I'm always open for all kinds of possibilities out there.
I usually name those columns Active (if there are only two statuses) and StatusId (if there is more than one status).