How is the record length affected in PSQL v9 when creating tables? - pervasive

I'm using Btrieve and the Pervasive SQL Control Center to create a table. The table has 3 columns: char 20, char 20, & char 50. The first column is the primary key. When I inserted a record through code the first character of the second column was always missing. I assumed because the first column was overwriting it. While investigating why I loaded up the File Information Editor. The File Specification lists the Record Length as 92. This doesn't make sense to me because I clearly defined the table as having record lengths of 90.
I was also getting error 22 which is indicative of differing record length of my buffer in code and the actual table record length.
To fix the missing first character in the second column, I changed my buffer in code so the first column was 21 chars in length. I also changed the 3rd column to be 51 to fix the error 22.
How does the record length get set to 92 in my example when I clearly defined the record lengths as 90 when creating the table?

What you are most likely seeing is an artifact of the "null" handling in Btrieve / Pervasive.
When you create a file using Btrieve, you layout the record exactly byte-by-byte. When "True Null" support was added to the Pervasive engine, any column created as nullable (the default) has an extra byte prefixing the field in the Btrieve file. This allows the engine to know if the field is null or an empty string.
Because your table had three columns, there should have been three extra bytes but because one of the columns was Primary Key, it does not all null so you only got two extra bytes.
In your case, if you had an existing Btrieve file and created the SQL definition, those extra fields wouldn't be there in some cases.
You have two options:
Recreate the table with "True Null" support turned off. This is done by issuing the Set TrueNullCreate = Off command before your Create Table command.
Add Not Null to all of the columns in the table and recreate the table.

Related

SQL Server : unique default values

I have a table with a column of type nchar(16) that is automatically filled with random characters generated by setting the default value of the column to dbo.randomtext((16)) (a scalar function). There will be about 1M records in the table.
I know that the likelihood of getting non-unique values is low, but is there some way to ensure that this does not happen and the column is really unique?
What will happen if I define the column as UNIQUE and the random text generated is not unique?
I am using SQL Server 2016 Standard edition.
Seems like what you should really be using is a SEQUENCE, IDENTITY or uniqueidentity and this smells like you are "reinventing" the wheel.
As for the questions you ask:
I know that the likelihood of getting non-unique values is low, but is there some way to ensure that this does not happen and the column is really unique?
Yes, create a UNIQUE INDEX or UNIQUE CONSTRAINT on the column. Then every row, must have a unique in that column.
What will happen if I define the column as UNIQUE and the random text generated is not unique?
If there is already at least one duplicate in the column, then creating the INDEX/CONSTRAINT will fail; you'll need to ensure you DELETE/UPDATE any duplicates before you can create the INDEX/CONSTRAINT. If it is an INSERT/UPDATE it will fail, and entire DML statement will not take affect (the new row(s) won't be inserted, or the row(s) won't be updated).

Reducing disk space of sql database

I got a database that have 2TB of data, and i wanna reduce it to 500Go by dropping some rows and removing some useless columns, but i have other ideas of optimizations, and i need an answer of some questions before.
My database got one .mdf file, and 9 other .ndf file and each file has an initiale size of 100Go.
Should I reduce the initiale size of each .ndf file to 50Go? can this operation affect my data?
Dropping an index help to reduce space?
PS : My Database contains only one single table, that has one clustered index and two other non clustered indexes,
I want to remove the two non clustered indexes
Remove the insertdate column
If you have any other ideas of optimizations, it would be very helpful
Before droping any indexes run these two views.
sys.dm_db_index_usage_stats
sys.dm_db_index_operational_stats
They will let you know if any of them are being used to support queries. The last thing you want is to remove an index and start seeing full table scans on a 2TB table.
If you can't split up the table into a relational model then try these for starters.
Check your data types.
-Can you replace NVARCHAR with VARCHAR or NCHAR with CHAR? (they take up half the space)
-Does your table experience a lot of Updates or a lot of Inserts (above view will tell you this)? If there are very few updates then consider changing CHAR fields to VARCHAR fields. Heavy updates can cause page splits and result in poor Page fullness.
-Check that columns only storing a Date with no time are not declared as Datetime
-Check value ranges in numeric fields i.e. try and use Smallint instead of Int.
Look at the activity on the table, update & insert behaviour. If the activity means very few Pages are re-arranged then consider increasing your Fill Factor.
Look at the Plan Cache, get an idea of how the table is being queried, if the bulk of queries focus on a specific portion of the table then implement a Filtered Index.
Is your Clustered Index Unique? If not then SQL creates a "hidden extra Integer column" that creates uniqueness under the bonnet.

Entering a comma delimited string into an INT column in SQL

I'm trying to add a comma delimited string into a column in my table set to INT.
I used it to reference a Category ID but now I'd like the possibility to add more than just 1 category.
Thinking I could accomplish this by entering a string like: 1,2,3 instead of just 1 but i'm getting errors that the changed value in this cell was not recognized as valid.
Does this mean I need to change that column to VARCHAR instead of INT?
No, this means that you should set up proper tables to support a 1-many relationship. That is, you want a separate table, not a bogus data representation in a varchar column.
Why? Well, SQL has this great data structure for lists, called a table. In addition:
Numbers should be stored in native format, not a string.
SQL has (relatively) poor functions for manipulating strings.
Operations on the column will not take advantage of indexes.
If the numbers represent ids in another table, you cannot declare proper foreign key references.

How can the date a row was added be in a different order to the identity field on the table?

I have a 'change history' table in my SQL Server DB called tblReportDataQueue that records changes to rows in other source tables.
There are triggers on the source tables in the DB which fire after INSERT, UPDATE or DELETE. The triggers all call a stored procedure that just inserts data into the change history table that has an identity column:
INSERT INTO tblReportDataQueue
(
[SourceObjectTypeID],
[ActionID],
[ObjectXML],
[DateAdded],
[RowsInXML]
)
VALUES
(
#SourceObjectTypeID,
#ActionID,
#ObjectXML,
GetDate(),
#RowsInXML
)
When a row in a source table is updated multiple times in quick succession the triggers fire in the correct order and put the changed data in the change history table in the order that it was changed. The problem is that I had assumed that the DateAdded field would always be in the same order as the identity field but somehow it is not.
So my table is in the order that things actually happened when sorted by the identity field but not when sorted by the 'DateAdded' field.
How can this happen?
screenshot of example problem
In example image 'DateAdded' of last row shown is earlier than first row shown.
You are using a surrogate key. One very important characteristic of a surrogate key is that it cannot be used to determine anything about the tuple it represents, not even the order of creation. All systems which have auto generated values like this, including Oracles sequences, make no guarantee as to order, only that the next value generated will be unique from previous generated values. That is all that is required, really.
We all do it, of course. We look at a row with ID of 2 and assume it was inserted after the row with ID of 1 and before the row with ID of 3. That is a bad habit we should all work to break because the assumption could well be wrong.
You have the DateAdded field to provide the information you want. Order by that field and you will get the rows in order of insertion (if that field is not updateable, that is). The auto generated values will tend to follow that ordering, but absolutely do not rely on that!
try use Sequence...
"Using the identity attribute for a column, you can easily generate auto-
incrementing numbers (which as often used as a primary key). With Sequence, it
will be a different object which you can attach to a table column while
inserting. Unlike identity, the next number for the column value will be
retrieved from memory rather than from the disk – this makes Sequence
significantly faster than Identity.
Unlike identity column values, which are generated when rows are inserted, an
application can obtain the next sequence number before inserting the row by
calling the NEXT VALUE FOR function. The sequence number is allocated when NEXT
VALUE FOR is called even if the number is never inserted into a table. The NEXT
VALUE FOR function can be used as the default value for a column in a table
definition. Use sp_sequence_get_range to get a range of multiple sequence
numbers at once."

Using 2 same values in 1 row -> SQL 2008 table

I've searched for this thingy a lot.. and I can not find a solution since I'm beginner in SQL itself.
I used to edit games database. now, I need to create a new table with 1 row called "CodeName128" and it should contain the same value many times..
when I place something like
CODE_NAME1
CODE_NAME1
it tells me No rows was updated blabla which means this table already have this code.
how can I get over it and enable the duplication in table?
Live example:
You must be having Primary key or Unique key defined on that column which is not allowing you to enter the duplicate values. The keys must be defined for a reason, so its not advisable to remove those, still if you think that duplicate values are required for that column, you have to alter the table structure and remove those constraints from that column.

Resources