Вычисления таблиц SQL Server в специальный столбец

Использование существующих свойств выполняется с помощью root или parent и довольно просто.

{
  "rules": {
    "things": {
      // assuming value is being stored as an integer
      ".validate": "newData.val() <= root.child('max')"
    }
  }
}

Однако определение количества записей и их принудительное выполнение несколько сложнее, чем просто написать правило безопасности:

  • , поскольку нет .length on объект, нам нужно сохранить, сколько записей существует
  • , нам нужно обновить это число в безопасном / реальном времени
  • , нам нужно знать номер записи, которую мы имеем добавление относительно этого счетчика

Наивный подход

. Один подход бедных людей, предполагая, что предел является чем-то небольшим (например, 5 записей), состоял бы в простом перечислении их в правилах безопасности:

{
  "rules": {
    "things": {
      ".write": "newData.hasChildren()", // is an object
      "thing1": { ".validate": true },
      "thing2": { ".validate": true },
      "thing3": { ".validate": true },
      "thing4": { ".validate": true },
      "thing5": { ".validate": true },
      "$other": { ".validate": false
    }
  }
}

Реальный пример

Такая структура данных, как это работает:

/max/
/things_counter/
/things/$record_id/{...data...}

Таким образом, каждый раз, когда добавляется запись , счетчик должен быть увеличен.

var fb = new Firebase(URL);
fb.child('thing_counter').transaction(function(curr) {
   // security rules will fail this if it exceeds max
   // we could also compare to max here and return undefined to cancel the trxn
   return (curr||0)+1;
}, function(err, success, snap) {
   // if the counter updates successfully, then write the record
   if( err ) { throw err; }
   else if( success ) {
      var ref = fb.child('things').push({hello: 'world'}, function(err) {
         if( err ) { throw err; }
         console.log('created '+ref.name());
      });
   }
});

И каждый раз, когда запись удаляется, счетчик должен быть уменьшен.

var recordId = 'thing123';
var fb = new Firebase(URL);
fb.child('thing_counter').transaction(function(curr) {
   if( curr === 0 ) { return undefined; } // cancel if no records exist
   return (curr||0)-1;
}, function(err, success, snap) {
   // if the counter updates successfully, then write the record
   if( err ) { throw err; }
   else if( success ) {
      var ref = fb.child('things/'+recordId).remove(function(err) {
         if( err ) { throw err; }
         console.log('removed '+recordId);
      });
   }
});

Теперь о правилах безопасности:

{
  "rules": {
    "max": { ".write": false },

    "thing_counter": {
      ".write": "newData.exists()", // no deletes
      ".validate": "newData.isNumber() && newData.val() >= 0 && newData.val() <= root.child('max').val()"
    },

    "things": {
      ".write": "root.child('thing_counter').val() < root.child('max').val()"
    }
  }
}

Обратите внимание, что это не заставляет пользователя писать в thing_counter перед обновлением записи, поэтому, хотя это подходит для ограничения количества записей, оно не подходит для обеспечения правил игры или предотвращения читов.

Другие ресурсы и Мысли

Если вы хотите защитить уровень игры, проверьте эту скрипту , в которой подробно описано, как создавать записи с инкрементными идентификаторами, включая правила безопасности, необходимые для обеспечения соответствия счетчику. Вы можете комбинировать это с приведенными выше правилами, чтобы обеспечить максимальное значение для инкрементных идентификаторов и обеспечить, чтобы счетчик обновлялся до записи записи.

Кроме того, убедитесь, что вы не слишком задумываетесь об этом, и есть законный прецедент для ограничения количества записей, а не просто для удовлетворения здоровой дозы беспокойства. Это сложная задача, чтобы просто обеспечить квоту бедного человека в ваших структурах данных.

-2
задан Yogesh Sharma 5 March 2019 в 15:33
поделиться

2 ответа

Используйте кумулятивные суммы:

select t.*,
       sum(cases - closed) over (order by year) as state
from t;

Я считаю state любопытным названием для кумулятивной суммы.

0
ответ дан Gordon Linoff 5 March 2019 в 15:33
поделиться

Вы хотите функцию окна:

select t.*,
       sum(cases - closed) over (order by year) as state
from table t;

РЕДАКТИРОВАТЬ: Для более старой версии вы можете использовать apply:

select t.*, t1.state
from table t cross apply 
     (select sum(t1.cases - t1.closed) as state
      from table t1
      where t1.yr <= t.yr
     ) t1;
0
ответ дан Yogesh Sharma 5 March 2019 в 15:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: