I'm working on a project in MVC 3 (first time using!). One question I keep running into is how to specify datatypes. For example, why have a field of type Nvarchar that has a length of 4000 when you only need a length of 10. As far as I can tell, there is no definitive compilation of specifying server data types for your database. I've been fairly successful so far (Below are some of the ones I've found), and please correct me if I am wrong. My main question is if there is a way to specify a Tinyint (1 byte) in MVC 3.
Here's some of the popular ones I've found:
Smallint: Specify field as Int16
Bigint: Specify field as Int64
Nvarchar(n): Add [StringLength(n)] above your variable in your Model
bit: Seems simple, but for first-time programmers - specify your field as a bool.
DateTime: There are so many flavors of DateTime, and to specify, initialize your field in your model as DateTime, and specify the type by placing [DataType(DataType.YourPreferredFormat)] above the variable, where "YourPreferredFormat" is a date/time related option of the enum DataType (DateTime, Date, Time, Duration). I'm not 100% clear on this though, so if anyone knows how each correlates, that would be great to know.
Per this answer to c-sharp-equivalent-of-sql-server-2005-datatypes it appears that you need to use Byte.
Related
I don't understand why implicit conversion isn't working for me for the median function in Oracle. (Obviously I have plenty of ways to work around it with proper explicit conversions, but I'm wondering why it's happening at all. Am I missing something obvious or is this a bug? It just seems so unlikely to be a bug.)
I have a table with a varchar2(255 byte) column. It's nullable, but contains no nulls. All of the strings in this field are numeric.
I can do this:
select avg(this_field) from this_table
and that's fine.
I can do this:
select median(to_number(this_field)) from this_table
and that's fine too.
But I can't do this:
select median(this_field) from this_table
because I get the error "ORA-30495: The argument should be of numeric or date/datetime type."
The Oracle documentation on MEDIAN says that implicit conversion is done:
This function takes as arguments any numeric data type or any
nonnumeric data type that can be implicitly converted to a numeric
data type.
This is the exact same wording as the Oracle documentation on AVG.
And yet:
select median(to_char('1')) from dual;
ORA-30495: The argument should be of numeric or date/datetime type.
select avg(to_char('1')) from dual;
1
select median(to_number(to_char('1'))) from dual;
1
So...what's going on?
That seems to be a documentation bug (which dates back to when it was first introduced in 10gR1). I imagine whoever wrote that copied and pasted from another function like avg, and didn't take out the bits that didn't apply for median.
Some functions, like trunc() and round(), allow either data type to be passed and also allow implicit conversion of strings to numbers - but not to dates, in my testing anyway. But those tend to be listed twice in the documentation with the different argument types, and are single-row functions; off-hand I can't think of any aggregates that behave like that.
avg() can arguably do implicit conversion because everything passed in has to be convertible to a number. They could have made median() only try to implicitly convert to number like trunc(), but perhaps there was too much overhead, or some implementation reason why it was difficult, or they planned to try to convert to dates as well; or maybe it was just overlooked.
The wording of that section would still have been wrong; the first paragraph states it takes a numeric or datetime value, so for the second to only refer to numeric would be incorrect anyway. It looks like the first sentence of that second paragraph shouldn't be there, and the rest should apply to datetimes as well, at least in terms of the return type.
There's a feedback button at the bottom of the left-hand navigation panel in the docs. You can report it there, and then see if the documentation is ever updated.
Alternatively, you could raise a service request to get the behaviour changed to match the docs - though that paragraph still needs some work...
Two possibilities come into my mind:
NUMBER(4)
DATE
Pro NUMBER(4):
No duplicate entries possible if specified as UNIQUE
Easy arithmetic (add one, subtract one)
Con NUMBER(4):
No Validation (e.g. negative numbers)
Pro DATE:
Validation
Con DATE:
Duplicate entries are possible ('2013-06-24', '2013-06-23', ...)
Not so easy arithmetic (add one = ADD_MONTHS(12))
As additional requirement the column gets compared with the current year EXTRACT (YEAR FROM SYSDATE). In my opinion NUMBER(4) ist the better choice. What do you think, is there another option I have missed?
You can restrict a date column to only have one entry per year if you want to, with a function-based index:
create unique index uq_yr on <table> (trunc(<column>, 'YYYY'));
Trying to insert two dates in the same year would give you an ORA-00001 error. Of course, if you don't want the rest of the date then it may be unhelpful or confusing to hold it, but on the other hand there may be secondary info you want to keep (e.g. if you're recording that an annual audit happened, holding the full date might not hurt anything). You could also have a virtual column (from 11g) that holds the trunc value for easier manipulation, perhaps.
You could also use an interval year(4) to month data type, and insert using numtoyminterval(2013, 'year'), etc. You could do interval arithmetic to add and subtract years, and extract to get the year back out as a number. That would probably be more painful than using a date though, overall.
If you're really only interested in the year (and you are not holding the month in a different column!) then a number is probably going to be simplest, with a check constraint to make sure it's a sensible number - number(4) doesn't stop you inserting 2.013 when you meant 2,013 (though you need to be converting from a string to hit that, and not have an NLS parameter mismatch), which would be truncated to just 2.
You've quite well summed up the pros/cons.
Provided that you name clearly your field so that it's easy to understand that it contains a year information, I would go with a NUMBER(4) for simplicity & storing no more or less than what is necessary. And even if there is no validation, IMO negative years are valid :)
Depending on your use case you might also consider building a one-off date (dimension) table and linking to a specific row via ID. That way, you have access to more information which you could later add to the dinemsion table (leap year etc.) and the entries in your dimension can be validated on creation.
Just want to know what are the corresponding datatype that I should declare when using DataMapper.
Types in MySQL
smallint
bit
varchar
Can anyone tell me the corresponding type in DataMapper?
Thanks.
According to this site you are fairly limited with no specific equivalents. Varchar somewhat equals string and integer seems to take the place of bigint. Bit is not mentioned at all. The idea is born out further by this link (click on show source) where you will see the adapter for MySQL maps the data types similar to above. Again, bit is not mentioned.
I have a little problem with Enterprise Architect by Sparx System.
Im trying to model database schema for Oracle. I created table with primary key with data type long. But when im trying to modify column properties (set AutoNum = true) I see empty properties. I read documentation of EA and saw that I need to setup this property to generate sequence syntax.
When I change data type to number, or switch database to mysql (for example) everything is alright, there are properties so Im able to modify AutoNum value.
Did you had similar problem and found solution ? or maybe im doing something wrong.
regards
It's becouse Oracle use sequence instead of autoincrement option. I've checked it and I think you have to use NUMBER column type and then set AutoNum property (you have to select Generate Sequences in options to get proper DDL code too). Instead of LONG data type you can set PRECISION and SCALE options on NUMBER type ie NUMBER(8) mean you can have 8 digits number and it can be set up to 38, so if you don't want to store info about every star in the universe will be enought for your scenario :)
I currently use INT as type for primary key in JavaDB (Apache Derby), but since I'm implementing an distributed system I would like to change the type to java.util.UUID. A few questions about this:
What datatype in JavaDB/Derby should I use for UUID? I have seen CHAR(16) FOR BIT DATA been mentioned but I don't know much about it. Is VARCHAR(16) an alternative?
How should I use it with JDBC? E.g. in an PreparedStatement, how should I set and get an UUID?
If I later would likte to change database to SQL Server, is there a compatible datatype to java.util.UUID?
Simply, How should I use UUID with JavaDB/Derby and JDBC?
UUID is a 128 bit value. The CHAR(16) FOR BIT DATA type reflects that it is bit data stored in character form for conciseness. I don't think VARCHAR(16) would work because it doesn't have the bit flag. The database would have to be able to convert the binary data to character data which deals with encoding and is risky. More importantly, it wouldn't buy you anything. Since a UUID is always 128 bits, you don't get the space savings from using VARCHAR over CHAR. So you might as well use the intended CHAR(16) FOR BIT DATA.
With JDBC, I think you use the get/setBytes() method since it is dealing with small amounts of binary data. (Not positive, would have to try this)
And no idea about the SQL Server part.
If you still want to use the UUID object in your code you can use fromString to create UUID objects from the DB and toString to store them in the DB.
You could convert the UUID to a string and store it as VARCHAR. Most UUID string formats are similar to this one: 32 digits separated by hyphens: 00000000-0000-0000-0000-000000000000, so then you'd want a VARCHAR(36), or make it something like VARCHAR(64) if you please, since it doesn't hurt to have extra 'space' available in your VARCHAR -- only the actual digits are stored.
Once you've converted it to a string, just call Statement.SetString to include it in your INSERT statement.