This question already has answers here:
Auto Increment after delete in MySQL
(18 answers)
Closed 12 months ago.
I want to know how can I make my SQL Database table give an ID starting from 0 and with every new add to check if there is an old ID free .
Exemple :
I added 10 items then I deleted almost everyone and I kept item with ID=5.
After adding a new item , it gets id 11 not 0.
Note : I'm editing my DB with Laravel API.
SQL AUTO INCREMENT adds 1 to the biggest incrementable column value.
To fill a free integer slot you need to check for it manually, but that kinda defeats the purpose of auto-incrementing.
Anyway here is how to check for the first free ID value:
function getUnusedId($ids_array)
{
$max_id = max($used_ids); // can be 25 for example
// [1:(id|1), 2:(id|2), 3:(id|3), 4:(id|5)] =>> ID 4 is missing
for($i = 1; $i <= $max_id; $i++){
if($used_ids[$i] > $i){
return $i;
}
}
return $max_id + 1; // You can echo that all IDs are used.
}
// The IDs must be ordered for this solution
$used_ids = Model::orderBy('id')->pluck('id')->toArray();
$free_id = getUnusedId($used_ids);
Related
I'm trying to write some code in Apps Script that triggers an email each time a condition is fulfilled in a Spreadsheet.
This spreadsheet contains the age of different transgenic lines of fish (the ages of the fish are automatically updated in the spreadsheet) and each of these transgenic lines has an associated caretaker with an email address. My idea is to trigger an automatic email using Apps script that is sent to the assigned caretaker each time one of these transgenic lines becomes older than 2 years old. However, I haven't been able to make it work yet. I'm not really sure which part of my code is preventing it from working properly.
Below I attach an example of how the spreadsheet would look like, as well as an example of the code that I've been trying to use (I'm a beginner when it comes to coding, so it's possible that there are many basic errors in it):
function fishalert() {
var subject = 'Fish aging alert';
var years = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1").getRange("C2:C10").getValues();
if (years > 2){
for(r=2;r<20;r++){
var name = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1").getRange(r,1).getValue();
var emailaddress = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1").getRange(r,4).getValue();
var message = 'Line ' + name + ' is more than 2 years old';
MailApp.sendEmail(emailaddress, subject, message);
}
}
}
Sending Email when conditions are met by sampling once a day
function fishalert(e) {
if (e['day-of-week'] < 6) {//sends emails mon through fri between 9 and 10 in the morning
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName('Sheet1');
const vs = sh.getRange(2, 1, sh.getLastRow() - 1, 4).getValues();
vs.forEach(r => {
if (r[2] > 2) {
MailApp.sendEmail(r[3], 'Fish aging alert', `Line ${r[0]} is more than 2 years old`);
}
});
}
}
Run this once:
function createTimeBasedTrigger() {
if(ScriptApp.getProjectTriggers().filter(t => t.getHandlerFunction() == 'fishalert').length == 0) {
ScriptApp.newTrigger('fishalert').timeBased().everyDays(1).atHour(9).create();
}
}
Time Driven Triggers
Time Driven Trigger Event Object
Class Range getValues() Method
For future enhancements
you will probably only want to send these emails on a less frequent schedule and probably only once when the threshold is achieved and you'll probably want to collect one email for each unique email address. But this is an answer to your current question
I had a problem with the mvc model updating a row.
The task was:
in table table_name set column_name = column_name + 1
If i would use the model like
model->find(...)
model->column_name = model->column_name + 1
model->save
then another script could have updated the column in the mean time:
model->find(...)
model->column_name = model->column_name + 1 // lets say loaded 9 and set to 10
// at this point another script may just loaded the old value 9
// and saved it to n.
// my current model would save to to 10 which would be wrong
model->save
To prevent that Im using the server:
$result = $this->getWriteConnection()->query(
"UPDATE `table_name` SET
`column_name` = #new_value := `column_name` + 1
WHERE ...;"
);
I then select the #new_value session var on another call.
What Im searching now is a way to do that with the mvc model.
Any way to do that?
This question already has answers here:
LINQ and pagination [duplicate]
(3 answers)
Closed 9 years ago.
I need to apply paging logic to this Query. How can i do that?
My query is as follows,
myresultset = from req in myreqTable
join streq in myStreqTable on req.ID.ToString() equals new SPFieldLookupValue( Convert.ToString( streq[FormID] ) ).LookupValue
where (filter(req) && filter1(streq))
join plnts in plantDetails on Convert.ToString( streq[RequestID) equals Convert.ToString(plnts[RequestID]) into mySet
from s in mySet.DefaultIfEmpty()
select new Mytable() {
FormID = Convert.ToString(streq[FormID]),
RequestID = Convert.ToString(streq[RequestID])
};
Add .Skip( pageSize * pageIndex ).Take( pageSize ); to the end of your query. Note that pageIndex is zero-based (so the first page is 0, the second page is 1 and so on).
However your Linq doesn't look valid to me, and has some syntax errors. Are you sure this is your code as it is in your editor?
recordsForCurrentPage = myresultset.Skip( recordsPerPage * pageNumber ).Take( recordsPerPage )
This is assuming that your page number starts with 0. Otherwise subtract 1 from pageNumber.
Use Take and Skip methods:
myresults = myresults.Skip((page - 1) * pageSize).Take(pageSize);
I assumed page numeration starts from 1.
I have a requirement to produce an "flattened" version of data for export, in which the customer wants the related table rows to appear as columns. We're using Entity Framework 4 & .NET 4.0
The customer has the ability to create custom questions for their events. There may be zero to infinite questions. Users attending the event may answer none, some or all of those questions.
What I need to produce is like this:
User 1 User 1 info field A User 1 info field B User 1 Answer to question A User 1 Answer to Question B
User 2 User 2 info field A User 2 info field B User 2 Answer to question A User 2 Answer to Question B
Creating the user info portion of the result set is not problem, but I'm stumped on how to take my related questions and answers, i.e.:
from urf in tblUserRegistrationFields.Include("tblRegistrationFields")
where urf.UserID == eachUserID && urf.tblRegistrationField.EventID == thisEventID
select new
{
FieldLabel = urf.tblRegistrationField.FieldLabel, //this is the question name
value = urf.value //this is the user's answer
}
And add those to my user select statement as individual columns, i.e.:
var users = from u in context.tblUsers
<snip>
select new
{
UserID = u.UserID,
<snip>,
CustomQuestionA = AnswerA,
CustomQuestionB = AnswerB,
... etc.
};
Ultimately I need to create a grid which I can then export to their desired format and I'm open to non-LINQ solutions (although the purchase of 3rd party controls is not an option.) I suspect there is a way to leverage LINQ's grouping features, but I haven't been able to apply it to this scenario.
I found a way to do dynamic pivots in SQL, but couldn't get it to work with two related tables, only with one. Dynamic SQL pivots here:
http://www.simple-talk.com/blogs/2007/09/14/pivots-with-dynamic-columns-in-sql-server-2005/
Ultimately, I fell back and created a dataset manually. It's certainly not an optimized solution, but it gives the customer what they want. I wouldn't recommend this approach for a high volume of data.
I create the dataset and datatable fixed columns, then loop through the list of questions:
//get the list of questions
var context = new EventRegistrationEntities();
var customQuestions = from rf in context.tblRegistrationFields
where rf.EventID == vEventID
select new
{
RegistrationFieldID = rf.RegistrationFieldID,
FieldLabel = rf.FieldLabel
};
//add a question column for each question
List<string> extracolumns = new List<string>();
foreach (var q in customQuestions)
{
dt.Columns.Add(q.FieldLabel, typeof(string));
//store the question names for later user
extracolumns.Add(q.RegistrationFieldID.ToString() + "-" + q.FieldLabel.ToString());
}
Next I then loop through the list of users and insert the fixed data, then within that loop (ugh) I add the users' answers:
foreach (var c in extracolumns) //these are the custom *questions*
{
int regID = Convert.ToInt32(c.Substring(0, c.IndexOf("-")));
string question = c.Substring(c.IndexOf("-") + 1); //we need to pass the question text (aka column header) in because if the user hasn't answered the question we have no access to it from here
//get the question answer
var userAnswer = (from urf in context.tblUserRegistrationFields.Include("tblRegistrationFields")
where urf.UserID == u.UserID && urf.RegistrationFieldID == regID
select new
{
Question = urf.tblRegistrationField.FieldLabel,
Answer = urf.value
}).FirstOrDefault();
//add the answer to the data row
if (userAnswer != null)
{
dr[question] = userAnswer.Answer.ToString();
}
else
{
dr[question] = ""; //if the user has not answered the question, insert a blank
}
}
I have met a problem about inserting multiple rows in a batch with Subsonic3. My development environment includes:
1. Visual Studio 2010, but use .NET 3.5
2. Active Record Mode in SubSonic 3.0.0.4
3. SQL Server 2005 express
4. Northwind sample database
I am using Active Reecord mode to insert mutiple "Product" into table "Products". If I insert the rows one by one, either call "aProduct.Add()" or call "Insert.Execute()" mutiple times (just like the codes below), it works fine.
private static Product[] CreateProducts(int count)
{
Product[] products = new Product[count];
for (int index = 0; index < products.Length; ++index)
{
products[index] = new Product
{
ProductName = string.Format("cheka-test-{0}", index.ToString()),
Discontinued = (index % 2 == 0),
};
}
return products;
}
private static void SucceedByMultiExecuteInsert()
{
Product[] products = CreateProducts(2);
// -------------------------------- prepare batch
NorthwindDB db = new NorthwindDB();
var inserts = from prod in products
select db.Insert.Into<Product>(x => x.ProductName, x => x.Discontinued).Values(prod.ProductName, prod.Discontinued);
// -------------------------------- batch insert
var selectAll = Product.All();
Console.WriteLine("--- before total rows = {0}", selectAll.Count().ToString());
foreach (Insert insert in inserts)
insert.Execute();
Console.WriteLine("+++ after inserting {0} rows, now total rows = {1}",
products.Length.ToString(), selectAll.Count().ToString());
}
but if I use "BatchQuery" like the codes below,
private static void FailByBatchInsert()
{
Product[] products = CreateProducts(2);
// -------------------------------- prepare batch
NorthwindDB db = new NorthwindDB();
BatchQuery batchquery = new BatchQuery(db.Provider, db.QueryProvider);
var inserts = from prod in products
select db.Insert.Into<Product>(x => x.ProductName, x => x.Discontinued).Values(prod.ProductName, prod.Discontinued);
foreach (Insert insert in inserts)
batchquery.Queue(insert);
// -------------------------------- batch insert
var selectAll = Product.All();
Console.WriteLine("--- before total rows = {0}", selectAll.Count().ToString());
batchquery.Execute();
Console.WriteLine("+++ after inserting {0} rows, now total rows = {1}",
products.Length.ToString(), selectAll.Count().ToString());
}
then it failed with the exception :
"
Unhandled Exception: System.Data.SqlClient.SqlException: Must declare the scalar variable "#ins_ProductName".
Must declare the scalar variable "#ins_ProductName".
"
Please give me some help to solve this problem. Many thanks.
I ran into this problem as well. If you look at the query it's attempting to run, you'll see it doing something like this (this isn't actual code but you'll get the point):
exec_sql N'insert into MyTable (SomeField) Values (#ins_SomeField)',N'#0 varchar(32)','#0=SomeValue'
For some reason it defines the parameters in the query with "#ins_"+FieldName but then passes the parameters as ordinals. I have yet to determine the pattern for why/when it does this but I've lost enough time during this dev cycle futzing with SubSonic to try and diagnose the problem properly.
The work-around I implemented will involve you downloading the 3.0.0.4 source from github and making a change on line 179 of Insert.cs.
Where it reads
ParameterName = _provider.ParameterPrefix + "ins_" + columnName.ToAlphaNumericOnly(),
Changing it to
ParameterName = _provider.ParameterPrefix + Inserts.Count.ToString(),
seemed to do the trick for me. I make no warranties about this solution for you, expressed or implied. It did work for me but your mileage may vary.
I should also note that there's similar logic around the "update" statements as well in Update.cs on lines 181 and 194 but I haven't had these give me problems... yet.
Honestly, I don't think SubSonic is ready for primetime and that's a shame because I really like how Rob set it up. That said, it's in my product for better or worse now so you make the best with what you got.